Pont Go-Frontend
Communication directe Go-JavaScript
Wails fournit un pont direct en mémoire entre Go et JavaScript, permettant une communication fluide sans surcharge HTTP, sans limites de processus et sans goulots d’étranglement liés à la sérialisation.
Vue d’ensemble
direction: right
Frontend: "Frontend (JavaScript)" {
UI: "React/Vue/Vanilla" {
shape: rectangle
style.fill: "#8B5CF6"
}
Bindings: "Auto-Generated Bindings" {
shape: rectangle
style.fill: "#A78BFA"
}
}
Bridge: "Wails Bridge" {
Encoder: "JSON Encoder" {
shape: rectangle
style.fill: "#10B981"
}
Router: "Method Router" {
shape: diamond
style.fill: "#10B981"
}
Decoder: "JSON Decoder" {
shape: rectangle
style.fill: "#10B981"
}
TypeGen: "Type Generator" {
shape: rectangle
style.fill: "#10B981"
}
}
Backend: "Backend (Go)" {
Services: "Your Services" {
shape: rectangle
style.fill: "#00ADD8"
}
Registry: "Service Registry" {
shape: rectangle
style.fill: "#00ADD8"
}
}
Frontend.UI -> Frontend.Bindings: "import { Method }"
Frontend.Bindings -> Bridge.Encoder: "Call Method('arg')"
Bridge.Encoder -> Bridge.Router: "Encode to JSON"
Bridge.Router -> Backend.Registry: "Find service"
Backend.Registry -> Backend.Services: "Invoke method"
Backend.Services -> Bridge.Decoder: "Return result"
Bridge.Decoder -> Frontend.Bindings: "Decode to JS"
Frontend.Bindings -> Frontend.UI: "Promise resolves"
Bridge.TypeGen -> Frontend.Bindings: "Generate types"Point clé : Pas de HTTP, pas d’IPC, pas de limites de processus. Juste des appels de fonction directs avec sécurité des types.
Comment ça marche : étape par étape
1. Enregistrement des services (Démarrage)
Lorsque votre application démarre, Wails analyse vos services :
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, "}),
},
})Ce que fait Wails :
- Analyse la structure pour trouver les méthodes exportées
- Extrait les informations de type (paramètres, types de retour)
- Construit un registre mappant les noms de méthodes aux fonctions
- Génère les liaisons TypeScript avec les définitions de type complètes
2. Génération des liaisons (Au moment de la compilation)
Wails génère automatiquement les liaisons TypeScript :
// Auto-generated: frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function Add(a: number, b: number): Promise<number>Mappage des types :
| Type Go | Type TypeScript |
|---|---|
string |
string |
int, int32, int64 |
number |
float32, float64 |
number |
bool |
boolean |
[]T |
T[] |
map[string]T |
Record<string, T> |
struct |
interface |
time.Time |
Date |
error |
Exception (levée) |
3. Appel Frontend (Exécution)
Le développeur appelle la méthode Go depuis 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) // 8Ce qui se passe :
- Fonction de liaison appelée -
Greet("World") - Message créé -
{ service: "GreetService", method: "Greet", args: ["World"] } - Envoyé au pont - Via le pont JavaScript de WebView
- Promise retournée - Attend la réponse
4. Traitement du pont (Exécution)
Le pont reçoit le message et le traite :
direction: down
Receive: "Receive Message" {
shape: rectangle
style.fill: "#10B981"
}
Parse: "Parse JSON" {
shape: rectangle
}
Validate: "Validate" {
Check: "Service exists?" {
shape: diamond
}
CheckMethod: "Method exists?" {
shape: diamond
}
CheckTypes: "Types correct?" {
shape: diamond
}
}
Invoke: "Invoke Go Method" {
shape: rectangle
style.fill: "#00ADD8"
}
Encode: "Encode Result" {
shape: rectangle
}
Send: "Send Response" {
shape: rectangle
style.fill: "#10B981"
}
Error: "Send Error" {
shape: rectangle
style.fill: "#EF4444"
}
Receive -> Parse
Parse -> Validate.Check
Validate.Check -> Validate.CheckMethod: "Yes"
Validate.Check -> Error: "No"
Validate.CheckMethod -> Validate.CheckTypes: "Yes"
Validate.CheckMethod -> Error: "No"
Validate.CheckTypes -> Invoke: "Yes"
Validate.CheckTypes -> Error: "No"
Invoke -> Encode: "Success"
Invoke -> Error: "Error"
Encode -> SendSécurité : Seuls les services enregistrés et les méthodes exportées sont appelables.
5. Exécution Go (Exécution)
La méthode Go s’exécute :
func (g *GreetService) Greet(name string) string {
// This runs in Go
return g.prefix + name + "!"
}Contexte d’exécution :
- S’exécute dans un goroutine (non bloquant)
- A accès à toutes les fonctionnalités Go (système de fichiers, réseau, bases de données)
- Peut appeler d’autres code Go librement
- Retourne le résultat ou une erreur
6. Réponse (Exécution)
Le résultat est renvoyé à JavaScript :
// Promise resolves with result
const greeting = await Greet("World")
// greeting = "Hello, World!"Gestion des erreurs :
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"
}Caractéristiques de performance
Vitesse
Surcharge d’appel typique : <1ms
Frontend Call → Bridge → Go Execution → Bridge → Frontend Response
↓ ↓ ↓ ↓ ↓
<0.1ms <0.1ms [varies] <0.1ms <0.1msComparé aux alternatives :
- HTTP/REST : 5-50ms (pile réseau, sérialisation)
- IPC : 1-10ms (limites de processus, marshalling)
- Wails Bridge : <1ms (en mémoire, appel direct)
Mémoire
Surcharge par appel : ~1KB (tampon de message)
Optimisation sans copie : Les données volumineuses (>1MB) utilisent la mémoire partagée lorsque cela est possible.
Concurrence
Les appels sont concurrents :
- Chaque appel s’exécute dans son propre goroutine
- Plusieurs appels peuvent s’exécuter simultanément
- Pas de blocage entre les appels
// These run concurrently
const [result1, result2, result3] = await Promise.all([
SlowOperation1(),
SlowOperation2(),
SlowOperation3(),
])Système de types
Types pris en charge
Primitifs
// 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]>Tranches et tableaux
// 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]) // 15Maps
// 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"Structures
// 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",---
**Des questions sur le pont ?** Posez-les sur [Discord](https://discord.gg/JDdSxwjhGf) ou consultez les [exemples de liaisons](https://github.com/wailsapp/wails/tree/master/v3/examples/binding).