Pular para o conteúdo

Ponte Go-Frontend

O Wails fornece uma ponte direta em memória entre Go e JavaScript, permitindo comunicação perfeita sem sobrecarga de HTTP, limites de processo ou gargalos de serialização.

Diagram

Insight principal: Sem HTTP, sem IPC, sem limites de processo. Apenas chamadas de função diretas com segurança de tipos.

Quando sua aplicação inicia, o Wails escaneia seus serviços:

type GreetService struct {
prefix string
}
func (g *GreetService) Greet(name string) string {
return g.prefix + name + "!"
}
func (g *GreetService) Add(a, b int) int {
return a + b
}
// Register service
app := application.New(application.Options{
Services: []application.Service{
application.NewService(&GreetService{prefix: "Hello, "}),
},
})

O que o Wails faz:

  1. Escaneia a estrutura em busca de métodos exportados
  2. Extrai informações de tipo (parâmetros, tipos de retorno)
  3. Constrói um registro mapeando nomes de métodos para funções
  4. Gera bindings de TypeScript com definições de tipo completas

O Wails gera bindings de TypeScript automaticamente:

frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function Add(a: number, b: number): Promise<number>

Mapeamento de tipos:

Tipo GoTipo TypeScript
stringstring
int, int32, int64number
float32, float64number
boolboolean
[]TT[]
map[string]TRecord<string, T>
structinterface
time.TimeDate
errorExceção (lançada)

O desenvolvedor chama o método Go do JavaScript:

import { Greet, Add } from './bindings/GreetService'
// Call Go from JavaScript
const greeting = await Greet("World")
console.log(greeting) // "Hello, World!"
const sum = await Add(5, 3)
console.log(sum) // 8

O que acontece:

  1. Função de binding chamada - Greet("World")
  2. Mensagem criada - { service: "GreetService", method: "Greet", args: ["World"] }
  3. Enviada para a ponte - Via ponte JavaScript do WebView
  4. Promise retornada - Aguarda resposta

A ponte recebe a mensagem e a processa:

Diagram

Segurança: Apenas serviços registrados e métodos exportados são chamáveis.

O método Go é executado:

func (g *GreetService) Greet(name string) string {
// This runs in Go
return g.prefix + name + "!"
}

Contexto de execução:

  • Executa em uma goroutine (não bloqueante)
  • Tem acesso a todos os recursos do Go (sistema de arquivos, rede, bancos de dados)
  • Pode chamar outro código Go livremente
  • Retorna resultado ou erro

O resultado é enviado de volta ao JavaScript:

// Promise resolves with result
const greeting = await Greet("World")
// greeting = "Hello, World!"

Tratamento de erros:

func (g *GreetService) Divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
try {
const result = await Divide(10, 0)
} catch (error) {
console.error("Go error:", error) // "division by zero"
}

Sobrecarga típica de chamada: <1ms

Frontend Call → Bridge → Go Execution → Bridge → Frontend Response
↓ ↓ ↓ ↓ ↓
&lt;0.1ms &lt;0.1ms [varies] &lt;0.1ms &lt;0.1ms

Comparado a alternativas:

  • HTTP/REST: 5-50ms (stack de rede, serialização)
  • IPC: 1-10ms (limites de processo, marshalling)
  • Wails Bridge: <1ms (em memória, chamada direta)

Sobrecarga por chamada: ~1KB (buffer de mensagem)

Otimização zero-copy: Dados grandes (>1MB) usam memória compartilhada quando possível.

Chamadas são concorrentes:

  • Cada chamada executa em sua própria goroutine
  • Múltiplas chamadas podem executar simultaneamente
  • Sem bloqueio entre chamadas
// These run concurrently
const [result1, result2, result3] = await Promise.all([
SlowOperation1(),
SlowOperation2(),
SlowOperation3(),
])
// Go
func Example(
s string,
i int,
f float64,
b bool,
) (string, int, float64, bool) {
return s, i, f, b
}
// TypeScript (auto-generated)
function Example(
s: string,
i: number,
f: number,
b: boolean,
): Promise<[string, number, number, boolean]>
// Go
func Sum(numbers []int) int {
total := 0
for _, n := range numbers {
total += n
}
return total
}
// TypeScript
function Sum(numbers: number[]): Promise<number>
// Usage
const total = await Sum([1, 2, 3, 4, 5]) // 15
// Go
func GetConfig() map[string]interface{} {
return map[string]interface{}{
"theme": "dark",
"fontSize": 14,
"enabled": true,
}
}
// TypeScript
function GetConfig(): Promise<Record<string, any>>
// Usage
const config = await GetConfig()
console.log(config.theme) // "dark"
// Go
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func GetUser(id int) (*User, error) {
return &User{
ID: id,
Name: "Alice",---
**Dúvidas sobre a ponte?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou verifique os [exemplos de binding](https://github.com/wailsapp/wails/tree/master/v3/examples/binding).