Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

veecore/jsgo

Repository files navigation

jsgo - Seamless Go/JavaScript Interop πŸš€

Go Reference CI Status

Production-Grade Go/JavaScript Type Conversion - The missing bridge for complex Go/WebAssembly applications

β†’ Why?
Go's syscall/js requires manual type handling. jsgo enables:

  • Automatic struct ↔ object conversion
  • JS Class inheritance (extends tag)
  • Complex type support (Dates, Functions, BigInt, Protobufs)
  • Familiar struct tags like jsgo:"fieldName,omitempty,extends=Parent"

πŸš€ Quick Start (Problem β†’ Solution)

Problem: Manual type conversion hell

// Old way - error-prone and tedious
js.Global().Set("user", map[string]any{
 "name": u.Name,
 "age": u.Age,
})

jsgo Solution:

package main
import (
 "github.com/veecore/jsgo"
 "syscall/js"
 "time"
)
type User struct {
 Name string `jsgo:"name"`
 Age int `jsgo:"age,omitempty"`
 Feelings func(at time.Time) string // can be executed js side with js Date as argument
}
func main() {
 user := User{Name: "Alice", Age: 30}
 jsVal, _ := jsgo.Marshal(user)
 js.Global().Set("user", jsVal)
}

Problem: Manual class inheritance

// Old way - fragile prototype chains
class MyGoClass extends Parent {
 constructor() {
 super(); // πŸ˜– Manual super handling
 }
}

jsgo Solution:

type Parent struct {
 js.Value `jsgo:",extends=HTMLElement"` // Inherit from browser API
}
jsgo.ExportGoType[Parent](nil)
type WebComponent struct {
 Parent `jsgo:",extends=Parent"` // Embedded parent
 State string `jsgo:"state"` // Custom fields
 private string // Unexported fields stay in Go
}
// Register as custom element
jsgo.ExportGoType[WebComponent](nil) // supports constructor
// Now use as native class!
customElements.define('my-component', window.WebComponent)

πŸ”‘ Key Differentiators

Feature jsgo Standard Library
Class Inheritance βœ… Prototype Chain ❌ Manual
Struct Tags βœ… Extends/Name ❌
Date ↔ Time βœ… Auto ❌ Manual
Cyclic Detection βœ… ❌
Constructor Control βœ… Super Args ❌
Production Benchmarks βœ… 5 allocs ❌
Function Handling βœ… Variadic/Auto ❌ Manual

πŸ›  Installation

go get github.com/veecore/jsgo@latest

πŸ— Class Inheritance Deep Dive

1. Simple Extension

type Animal struct {
 js.Value `jsgo:",extends=BaseCreature"`
 Legs int `jsgo:"limbs"`
}
// JS: class Animal extends BaseCreature { ... }

2. Custom Super Arguments

cfg := jsgo.ConstructorConfig{
 Fn: func(size int) *Widget {
 return &Widget{Size: size*2}
 },
 SuperArgs: func(args []js.Value) []js.Value {
 return []js.Value{js.ValueOf("processed")}
 },
}
jsgo.ExportGoTypeWithName[Widget](cfg, "AdvancedWidget")

πŸ“ˆ Real-World Use Cases

Web Component Framework

type WebButton struct {
 jsgo.Value `jsgo:",extends=HTMLButtonElement"`
 Theme string `jsgo:"data-theme,mustBe"`
}
// Constructor with theme validation
func NewButton(theme string) (*WebButton, error) {
 if theme == "" {
 return nil, errors.New("Theme required")
 }
 return &WebButton{Theme: theme}, nil
}
// Export as custom element
jsgo.ExportGoTypeWithName[WebButton](
 NewButton, 
 "MaterialButton",
)
// Browser usage
const btn = new MaterialButton("dark");
document.body.appendChild(btn);
btn.dataset.theme = "light"; // Type-safe updates

πŸ† Performance Matters

Competitive with handwritten implementations while maintaining developer ergonomics

Benchmark jsgo Performance Handwritten Advantage
Marshaling
Complex Struct 431k ops/sec 367k ops/sec -17%
Primitive Types 1.8M ops/sec - _
Unmarshaling 589k ops/sec 367k ops/sec +38%
Memory Efficiency 5 allocs/op 25+ allocs/op 5x
# Object key
input_size_10 106,949 ns/op (5 allocs)
input_size_2000 1,392,638 ns/op (5 allocs) # 13x slower for 200x data
# Vanilla JS approach comparison
input_size_2000 60,768,849 ns/op (5992 allocs) # 43x slower than GoField
# Class creation (50k ops/sec)
BenchmarkClassCreate-12 50,265 ops/s 19.8ΞΌs/op 0 B/op
# Method calls (1.2M ops/sec)
BenchmarkMethodCall-12 1,234,548 ops/s 812ns/op 0 B/op

About

Go-WASM Interop Done Right: Export Any Go Function to JS + Type-Safe Marshaling Struct tags (`jsgo:"field"`), JS class inheritance, cycle detection, and zero `js.Value` boilerplate.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

Contributors

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /