Gio UI - GUI multiplataforma para Go
(gioui.org)- Biblioteca que permite a desenvolvedores Go criar uma GUI de modo imediato para vários sistemas operacionais e WebAssembly
- Suporta Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD e WebAssembly, com amplo alcance de plataformas
- Projetada para reduzir dependências, usando bibliotecas de plataforma para gerenciamento de janelas, entrada e renderização por GPU
- A renderização inclui o renderizador vetorial Pathfinder baseado em OpenGL ES e Direct3D 11, e está migrando para um renderizador de compute shader baseado em piet-gpu
- Texto e formas são renderizados por contornos, sem serem pré-gravados em texturas, oferecendo suporte a animações, desenho com transformações e independência da resolução em pixels
Objetivo e escopo de suporte do Gio
- Gio é uma biblioteca para criar GUIs eficientes, fluidas e portáveis em Go
- As plataformas suportadas são Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD e WebAssembly
- Há uma demo WebAssembly para testes rápidos, e é necessário um navegador com suporte a WebAssembly para executá-la
- O código-fonte de exemplo pode ser visto no projeto Kitchen
Instalação e caminho de aprendizado
- O Gio foi projetado com foco em poucas dependências
- Você pode verificar as dependências necessárias na documentação de instalação de cada plataforma
- Após a instalação, é possível começar pela documentação Learn e pelo Hello World
- O showcase inclui godcr, Tailscale, gotraceui, Sointu, Protonet e outros
Tecnologia de renderização
- O Gio combina a flexibilidade do paradigma gráfico de modo imediato com tecnologias modernas de gráficos 2D
- O renderizador vetorial é baseado no projeto Pathfinder e implementado sobre OpenGL ES e Direct3D 11
- O renderizador está migrando para um renderizador baseado em compute shader mais eficiente, construído sobre piet-gpu
- Texto e formas são renderizados usando apenas contornos, sem pré-gravação em imagens de textura
- Suporta animações eficientes
- É adequado para desenho com transformações
- Pode manter independência da resolução em pixels
Modelo de financiamento
- O desenvolvimento do Gio é financiado por patrocínio
- Se o projeto for útil, você pode considerar apoiar o projeto Gio no OpenCollective ou patrocinar diretamente o desenvolvedor
1 comentários
Opiniões no Hacker News
Usando na prática, foi impossível criar com isso um app complexo sério
Ele não tem componentes que outras plataformas oferecem por padrão, como vídeo, mapas e rich text, e também não há um caminho claro e fácil para adicioná-los por conta própria
A API quebra a cada poucos meses, e também não há uma forma de aplicar temas
Gráficos em modo imediato são bons até você precisar gerenciar estado complexo, mas a partir daí acaba tendo que implementar seu próprio sistema de gráficos em modo retido, trazendo de volta problemas que foram resolvidos há muito tempo
O renderizador sofisticado baseado em
piet-gputambém só aceita pontos de controle de curvas de Bézier como entrada e faz a tesselação de tudo; a ideia é interessante, mas, para desenhar um círculo de verdade, você acaba dependendo de uma aproximação com 4 curvas de BézierWasm parece mais uma prova de conceito que a equipe de compilação ainda precisaria lapidar por anos em termos de engenharia para chegar a nível de produto; no geral, parece ok quando desenvolvedores Go querem criar uma UI simples, com algo como listas e campos de entrada
Há também tema Material Design e modos claro/escuro
Um ótimo exemplo de app gioui com modos claro/escuro e tema customizado é https://github.com/chapar-rest/chapar
No Mac ou no Windows, basta
go run .Kerning de texto, texto fluindo ao longo de arcos e RTL/LTR também são possíveis graças a
github.com/go-text/typesettingWidgets complexos, como seletores giratórios de calendário ou diagramas, também existem no GitHub, mas falta um esforço para reuni-los
Se essas coisas forem agregadas, acho que haverá incentivo suficiente para mais desenvolvedores entrarem
Parece não haver uma cultura que valorize não quebrar o código dos usuários
Ambos hoje são estáveis e têm um conjunto de controles e bibliotecas relativamente rico
Na web, parece renderizar tudo em um canvas, como o Flutter, e essa abordagem é conhecida por ter problemas de acessibilidade e de sensação nativa
Não dá para navegar com Tab entre botões de opção; no macOS,
CMD+Anão seleciona todo o conteúdo do campo de texto, enquantoCTRL+AfuncionaParece possível, mas também exigiria bastante trabalho
Fugindo um pouco do assunto, mas tenho curiosidade sobre qual é hoje a melhor forma de criar apps multiplataforma para mobile e web
Seja compartilhando tanto a lógica de negócio quanto a UI, seja compartilhando só a lógica de negócio
Fiquei em dúvida entre opções como gomobile, Rust e TypeScript
Por um tempo, TypeScript pareceu a tecnologia mais portátil, então pensei em usá-lo para toda a lógica de negócio, mas descobri que não há uma boa forma de rodar JavaScript no iOS com desempenho decente
Se você não se importar em escrever a UI nativa e compartilhar apenas a lógica de negócio, Kotlin também é uma opção: https://kotlinlang.org/docs/multiplatform.html#kotlin-multip...
Com Compose, também é possível criar a UI em Kotlin: https://www.jetbrains.com/lp/compose-multiplatform/
Porém, o suporte a iOS ainda está em alfa e o da web é “experimental”; então, se você não quiser aceitar a possibilidade de ter de mudar código conforme o framework evolui, Flutter, que já é bastante estável em todas as plataformas, é a escolha certa
Se você já conhece TypeScript e React, também pode considerar React Native, mas é difícil garantir o desempenho no iOS ou em outros lugares: https://reactnative.dev/
Já passei por frameworks demais que prometiam resolver tudo e não cumpriam
No começo você começa mais rápido, mas logo acaba remendando bibliotecas centrais depois de uma atualização do OS para chegar a FPS próximo do nativo ou para deixar as animações do sistema mais parecidas
Você só economiza tempo quando não lapida a UI
A lógica central pode ser compartilhada
Uso gomobile e gosto bastante no geral, mas o overhead de runtime é de 3 MB, então não serve para web
Kotlin Multiplatform parecia bom, mas faltavam bibliotecas básicas e, talvez por elas já existirem no Kotlin Android, pouca gente fazia equivalentes multiplataforma
Rust e a camada de bindings de linguagem da Mozilla também parecem bons, mas ainda não experimentei
Flutter também não é ruim, mas na web ele renderiza em canvas, o que é ruim em termos de sensação de uso e acessibilidade
O iOS também ainda tem problemas de latência mesmo depois da introdução do motor de renderização Impeller
Olhando para o cliente do Bluesky, o desempenho é bom em todas as plataformas suportadas e ele usa uma única base de código
https://github.com/bluesky-social/social-app
É open source e tem como alvo Android, iOS, Windows, Mac e Linux: https://platform.uno/platforms/
Usa C# e implementa automaticamente views e controles com o framework de UI nativo de cada plataforma
Também tem bom suporte a IDEs como Visual Studio, VS Code e Rider, e não fica limitado a outras ferramentas
Há também um plugin para Figma voltado à colaboração de design
Não sei se é uma boa ferramenta também para produtos de consumo
Para o nosso uso, funciona bem o suficiente, principalmente porque são ferramentas para técnicos de usinas solares, e usar TypeScript multiplataforma em ambientes com internet ruim ficou pesado demais para uma equipe pequena
Estou criando um app de streaming com gioui, e é muito fácil; os upgrades também são sempre tranquilos
Porque é Go e os desenvolvedores principais tratam mudanças com bastante seriedade
Quando preciso de uma GUI web, uso este sistema de plugins do gioui: https://github.com/gioui-plugins/gio-plugins
É surpreendente que o WebView funcione na web, no desktop e no mobile
Deep links também funcionam: ao enviar links por e-mail ou em notificações do Monike, o app do usuário abre exatamente na posição correta da GUI
Também há notificações e extensões de compartilhamento para todos os sistemas operacionais, então acho que é realmente algo próximo de um sistema completo
Concordo que dar suporte a todos os sistemas operacionais é difícil, mas no mundo de hoje a diversidade é o padrão
Gosto do fato de poder fazer tudo isso só com Go, sem ficar alternando entre várias tecnologias
Sempre escrevo o backend em Go para funcionar tanto com gio quanto com HTML
Se preciso de SEO ou reprodução de vídeo, trato isso no WebView, e também consigo atender ao SEO do Google no lado web do gio
Coloco Markdown no Hugo para que o SEO do Google enxergue
Do ponto de vista de alguém iniciante em Go, esta parte da documentação me deixou curioso
Diz que o motivo para usar
op.ColorOp{Color: red}.Add(ops)em vez deops.Add(ColorOp{Color: red})é evitar alocações na chamada, fazendo com que o métodoAddnão receba um argumento de tipo interface, e que isso é central no design de “zero allocation” do GioGostaria de entender por que surge uma alocação, o que é alocado e como isso é economizado
Quando uma função recebe um argumento de tipo interface e você passa para ela uma struct pura, Go cria um wrapper em volta dela, e essa é a alocação mencionada na citação
Esse wrapper é um par de ponteiros formado por um ponteiro de tipo/vtable e um ponteiro para os dados da struct
Isso permite inferência de tipo em tempo de execução e extensão implícita de interfaces
Ou seja, para implementar uma interface basta implementar os métodos, sem precisar declarar explicitamente o tipo como em
ByteReader extends ReaderVocê só paga esse custo quando usa isso, então muito código em caminhos rápidos usa apenas structs sempre que possível
v := interfaceType(concreteTypeValue), em baixo nível acontece mais ou menos istoAlgo como
dataPtr := &concreteTypeValue,typePtr := typeData[concreteType](), e então é criado um valor de interface com o ponteiro de dados e o ponteiro de tipoA primeira linha aqui é a alocação, porque, pela regra que lembro, ponteiros em Go não apontam para valores na stack, então
concreteTypeValueprecisa ser alocado no heapA regra de ponteiros não apontarem para a stack existe para facilitar o crescimento dinâmico das stacks das goroutines
Veja https://go.dev/doc/faq#stack_or_heap
ColorOp{Color: red}precisa ser encaixotado e alocado no heapIsso porque
ops.Addnormalmente recebe um ponteiro “gordo” para um valor que implementa uma certa interface, e não um valor de tipo concretoop.ColorOp{Color: red}.Add(ops)soa estranho de lerPara mim, parece “adicionar
opsao resultado deop.ColorOp{Color: red}”Por isso eu daria à função o nome
AddTo:op.ColorOp{Color: red}.AddTo(ops)Ainda não é exatamente idiomático, mas pelo menos sinaliza que o argumento da função é modificado
É interessante que a demo em WASM da primeira página, em um PC bem comum com Windows 10 e Chrome, renderiza apenas quadrados pretos onde deveria haver texto
No Chrome de um celular Android, renderizou corretamente
Além disso, rodou extremamente devagar
Fiz um pequeno app em Go usando Fyne e não pretendo usar de novo
Tanto Gio quanto Fyne carecem muito do polimento e dos recursos que o Flutter oferece
Decidi fazer a lógica principal em Golang e embrulhá-la em um app Android, mas a GUI parecia ter saído de 2003 e as opções para consertar isso eram limitadas
Você pode escrever toda a lógica em Go e a UI em HTML, usando ou não um framework web
É parecido com Electron, mas mais leve porque não distribui o Chrome junto e usa o visualizador web do sistema
[1] https://github.com/wailsapp/wails
Seria ótimo se você pudesse explicar como embrulhou isso como app Android
Por que todas essas GUIs multiplataforma parecem ter sido desenhadas 50 anos atrás?
A demo não funciona para mim
No Chromium do Win 11, alguns botões aparecem, mas a maior parte está toda preta
Ao contrário do Fyne, é um bom sinal que esta biblioteca tenha passado no primeiro teste que joguei nela: renderização de texto CJK
O Fyne não consegue fazer isso a menos que você forneça uma única fonte customizada para renderizar tudo
Boa sorte para encontrar uma única fonte que inclua de forma satisfatória todos os sistemas de escrita comuns no mundo inteiro, além de emojis
Então, quando estou criando algo que tenha conteúdo gerado por usuários, conteúdo web ou qualquer possibilidade de localização, por menor que seja, o Fyne está imediatamente fora para mim