Migre do Go 1.11 para o runtime do Go mais recente

Esta página aborda as instruções para migrar dos motores de execução Go de primeira geração para os de segunda geração. Para atualizar a sua app de segunda geração para usar a versão mais recente suportada do Go, consulte o artigo Atualize uma aplicação existente.

O Go 1.11 atingiu o fim do apoio técnico a 30 de janeiro de 2024. As suas aplicações Go 1.11 existentes vão continuar a ser executadas e a receber tráfego. No entanto, o App Engine pode bloquear a nova implementação de aplicações que usam tempos de execução após a data de fim do suporte. Recomendamos que migre para o tempo de execução suportado mais recente do Go seguindo as diretrizes nesta página.

A migração para um tempo de execução do Go de segunda geração suportado permite-lhe usar funcionalidades de linguagem atualizadas e criar apps mais portáteis, com código idiomático.

Alterações nos tempos de execução de segunda geração

Considere as seguintes diferenças ao atualizar para um tempo de execução do Go de segunda geração suportado:

  • Para reduzir o esforço e a complexidade da migração em tempo de execução, o ambiente padrão do App Engine permite-lhe aceder a muitos dos serviços e APIs agrupados antigos nos tempos de execução de segunda geração, como o Memcache. A app Go de segunda geração pode chamar as APIs de serviços incluídas através do SDK do App Engine para Go e aceder à maioria das mesmas funcionalidades que no tempo de execução do Go 1.11.

    Também tem a opção de usar Google Cloud produtos que oferecem funcionalidades semelhantes aos serviços incluídos antigos. Estes Google Cloud produtos oferecem bibliotecas de cliente da nuvem idiomáticas para Go. Para os serviços incluídos que não estão disponíveis como produtos separados no Google Cloud, como o processamento de imagens, a pesquisa e as mensagens, pode usar fornecedores externos ou outras soluções alternativas.

    Para saber mais sobre a migração para serviços desagrupados, consulte o artigo Migrar de serviços agrupados.

  • O comportamento de alguns elementos no ficheiro de configuração app.yaml foi modificado. Para mais informações, consulte o artigo Alterações ao ficheiro app.yaml.

  • O início de sessão no tempo de execução de segunda geração segue a norma de registo no Cloud Logging. Nos runtimes de segunda geração, os registos de apps já não são incluídos nos registos de pedidos, mas são separados em registos diferentes. Para saber como ler e escrever registos nos runtimes de segunda geração, consulte o guia de registo.

Diferenças na utilização de memória

Os tempos de execução de segunda geração têm uma base de utilização de memória mais elevada em comparação com os tempos de execução de primeira geração. Isto deve-se a vários fatores, como diferentes versões de imagens base e diferenças na forma como as duas gerações calculam a utilização de memória.

Os runtimes de segunda geração calculam a utilização de memória da instância como a soma do que um processo de aplicação usa e o número de ficheiros de aplicação armazenados em cache dinamicamente na memória. Para evitar que as aplicações com utilização intensiva de memória sofram encerramentos de instâncias devido à ultrapassagem dos limites de memória, atualize para uma classe de instância maior com mais memória.

Diferenças na utilização da CPU

Os tempos de execução de segunda geração podem observar uma base mais elevada de utilização da CPU no início a frio da instância. Consoante a configuração de escalabilidade de uma aplicação, isto pode ter efeitos secundários não intencionais, como um número de instâncias superior ao previsto, se uma aplicação estiver configurada para ser dimensionada com base na utilização da CPU. Para evitar este problema, reveja e teste as configurações de escalabilidade da aplicação para garantir que o número de instâncias é aceitável.

Diferenças nos cabeçalhos dos pedidos

Os tempos de execução de primeira geração permitem que os cabeçalhos de pedidos com carateres de sublinhado (por exemplo, X-Test-Foo_bar) sejam encaminhados para a aplicação. Os tempos de execução de segunda geração introduzem o Nginx na arquitetura do anfitrião. Como resultado desta alteração, os tempos de execução de segunda geração estão configurados para remover automaticamente os cabeçalhos com carateres de sublinhado (_). Para evitar problemas com a aplicação, evite usar carateres de sublinhado nos cabeçalhos dos pedidos da aplicação.

Alterações ao ficheiro app.yaml

O comportamento de alguns elementos no ficheiro de configuração app.yaml foi modificado:

Elemento Alterar tipo Descrição
app_engine_apis Obrigatório para apps que usam serviços agrupados antigos Tem de estar definido como true se quiser aceder aos serviços incluídos antigos para os tempos de execução de segunda geração.
login Suportado se app_engine_apis for true Se não estiver a usar os serviços agrupados antigos para os runtimes de segunda geração, use estes métodos alternativos para autenticar utilizadores.
runtime Modificado Altere o elemento runtime para especificar um tempo de execução de segunda geração.

Para mais informações, consulte a app.yaml referência.

Crie um pacote de main

O seu serviço tem de incluir uma declaração package main em, pelo menos, um ficheiro de origem.

Serviços agrupados antigos do App Engine

Se o seu serviço usar os serviços agrupados antigos para os tempos de execução de segunda geração:

  • O seu serviço só pode usar pacotes v2 (google.golang.org/appengine/v2). A utilização dos pacotes v1 (google.golang.org/appengine) mais antigos provoca erros.

  • Na função main(), chame appengine.Main() em vez de http.ListenAndServe(). Isto garante que as APIs user e appengine têm acesso ao contexto do pedido atual.

Escrever um pacote principal

Se o seu serviço ainda não contiver um pacote main, adicione a declaração package main e escreva uma função main(). No mínimo, a função main() deve:

  • Leia a variável de ambiente PORT e chame a função http.ListenAndServe():

    port := os.Getenv("PORT")
    if port == "" {
    	port = "8080"
    	log.Printf("Defaulting to port %s", port)
    }
    
    log.Printf("Listening on port %s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
    	log.Fatal(err)
    }

Registar os seus controladores HTTP

Pode registar os seus controladores HTTP escolhendo uma das seguintes opções:

  • O método preferencial é mover manualmente todas as chamadas http.HandleFunc() dos seus pacotes para a função main() no pacote main.
  • Em alternativa, importe os pacotes da sua aplicação para o pacote main, garantindo que cada função init() que contenha chamadas para http.HandleFunc() é executada no arranque.

    Pode encontrar todos os pacotes que usam a chamada http.HandleFunc() com o seguinte script bash e copiar o resultado para o bloco import do seu pacote main:

    gp=$(go env GOPATH) && p=$(pwd) && pkg=${p#"$gp/src/"} && find . -name "*.go" | xargs grep "http.HandleFunc" --files-with-matches | grep -v vendor/ | grep -v '/main.go' | sed "s#\./\(.*\)/[^/]\+\.go#\t_ \"$pkg/\1\"#" | sort | uniq
    

Estruturar os seus ficheiros

O Go requer que cada pacote tenha o seu próprio diretório. Pode indicar ao App Engine onde se encontra o pacote main através de main: no ficheiro app.yaml do projeto. Por exemplo, se a estrutura de ficheiros da sua app tiver o seguinte aspeto:

myapp/
├── app.yaml
├── foo.go
├── bar.go
└── web/
    └── main.go

O seu ficheiro app.yaml teria:

main: ./web # Relative filepath to the directory containing your main package.

Para mais informações sobre a flag main, consulte a app.yaml referência.

Mover ficheiros para o seu GOPATH

Encontre o seu GOPATH através do seguinte comando:

go env GOPATH

Mova todas as importações e ficheiros relevantes para o seu GOPATH. Se usar importações relativas, como import ./guestbook, atualize as suas importações para usar o caminho completo: import github.com/example/myapp/guestbook.