A parte declarativa da importação de pacotes para o Go é bastante entediante e mundana. Você só precisa especificar a diretiva de import
e listar os pacotes importados. Os IDEs modernos fazem esse trabalho para você - eles próprios substituem os pacotes nesta seção, o que é muito conveniente. Além disso, eles recolhem esse bloco para que não interfira na exibição do código. Aconselho você a expandir esse bloco e estudá-lo com cuidado - talvez você encontre algo incomum lá:
package main import ( "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" _ "github.com/vigo5190/goimports-example/c" )
Se a importação padrão, importe com um sinônimo e _
eu conheci, importe de .
Eu não vi antes.
Para iniciantes, vale lembrar como os programas no Go são lançados.
A primeira e mais importante coisa - na raiz do projeto (para bibliotecas e pacotes de outra forma) está o arquivo main.go
, que, quando desenvolvido, é executado por
go run main.go
Uma característica distinta desse arquivo é que o pacote declarado nele deve ser main
.
package main import ( "fmt" ) func main() { fmt.Println("Hello habr.com!") }
Essencialmente, o ponto de entrada para o programa é func main()
no pacote main
. Mas esse comportamento pode ser um pouco invadido . A func init()
foi inventada para isso. Esta função será executada antes de executar a func main()
. Esta função também pode ser escrita em seus pacotes. Ele sempre será executado quando um pacote for importado (para ser mais preciso, será executado uma vez que um pacote for importado no seu programa). Também vale a pena entender que o init()
será executado quando os testes deste pacote forem executados.
Exemplos de Pacotes
O pacote a
exporta apenas a variável, mas não a inicializa.
github.com/vigo5190/goimports-example/a O pacote b
exporta a variável e a inicializa para init()
.
github.com/vigo5190/goimports-example/b package b var Foo string func init() { Foo = "bar" }
O pacote c
exporta a variável, inicializa-a para init()
e exibe o valor em stdout.
github.com/vigo5190/goimports-example/c package c import "fmt" var Foo string func init() { Foo = "bar" fmt.Printf("%#v\n", Foo) }
Importar "simples"
Neste exemplo, importamos 2 pacotes e produzimos os valores das variáveis exportadas para o stdout.
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", b.Foo) }
Nós temos
go run main.go "" "bar"
O que realmente acontece neste código. Na seção de import
, 2 pacotes b
importados. No pacote a
variável com um valor padrão é declarada (para cadeias - uma cadeia vazia). No pacote b
, o valor da variável foi inicializado em init()
valor "bar"
. Para acessar as variáveis de cada pacote, use uma entrada no formato <_>.<_>
.
Importar sinônimo
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/b" bar "github.com/vigo5190/goimports-example/a" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", foo.Foo) fmt.Printf("%#v\n", bar.Foo) }
Nós temos
go run main.go "" "bar" ""
Como você pode ver no exemplo, o pacote b
recebe o sinônimo foo
. Nesse caso, o pacote a
importado várias vezes - a segunda vez na bar
alias.
Os pacotes são importados definindo sinônimos em vários casos:
- O nome do pacote importado é inconveniente / feio / ... e eu quero usar outro;
- O nome do importado cruza com o nome de outro pacote;
- Desejo substituir perfeitamente o pacote - as interfaces do pacote devem corresponder.
Exemplo de uso justificável de um sinônimoPor exemplo, ao importar github.com/sirupsen/logrus
:
package db import( log "github.com/sirupsen/logrus" )
Importar sublinhado
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" _ "github.com/vigo5190/goimports-example/c" ) func main() { fmt.Printf("%#v\n", a.Foo) }
Nós temos
go run main.go "bar" ""
Como o código mostra, importamos dois pacotes: a
e c
. Ao mesmo tempo, o pacote c
precedido por _
e o próprio pacote não é usado de forma alguma. Essa técnica é usada para executar init()
de um pacote.
No nosso exemplo, "bar"
apareceu na saída na primeira linha, porque esta saída está na função de inicialização do pacote c
.
Exemplo de uso justificado _Por exemplo, ao importar github.com/lib/pq
:
package db import( _ "github.com/lib/pq" )
em init()
lib/pq
o código é:
func init() { sql.Register("postgres", &Driver{}) }
que registrará o driver.
Importar ponto c
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", Foo) }
Nós temos
go run main.go "" "bar"
A importação com um ponto adiciona todos os campos exportados do pacote ao escopo atual (mais precisamente, o escopo do arquivo). E agora você pode trabalhar com os campos do pacote importado como se estivessem no seu pacote.
Esta opção deve ser usada com muito cuidado - um exemplo abaixo.
Exemplo 1 package main import ( . "fmt" ) func main() { Println("Hello, habr.com!") }
Temos:
Hello, habr.com!
Exemplo 2 package main import ( . "fmt" . "math" ) func main() { Printf("%v\n", Sqrt(9)) }
Temos:
3
Importar com ponto (e erro)
package main import ( "fmt" . "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", Foo) }
Nós temos
go run main.go
Como você pode ver na saída, ao importar pacotes com campos cruzados para o escopo atual, obtemos um erro de compilação.
Portanto, pense novamente antes de usar essa importação - é possível obter um erro completamente inesperado.
Total
Apesar das rígidas limitações de sintaxe, você pode fazer várias coisas fora do padrão no Go. Os recursos de importação discutidos acima demonstram que, com apenas alguns operadores, você pode alterar muito o comportamento de um programa. O principal, ao usar todas essas oportunidades, não é dar um tiro no próprio pé . E lembre-se de que é melhor escrever um código simples e compreensível do que um código complexo e "legal".
PS
Exemplos de código para brincar estão no github .