Execute Formate

Go Efetivo

Introdução

Go é uma nova linguagem. Embora com idéias emprestadas de linguagens existentes, tem propriedades incomuns que fazem programas Go eficazes e diferentes em relação de programas escritos em seus parentes. A tradução direta de um programa em C++ ou Java em Go é susceptível de produzir um resultado satisfatório — programas Java são escritos em Java, não Go. Por outro lado, pensar sobre o problema a partir de uma perspectiva Go poderá produzir um bem-sucedido, mas bastante diferente programa. Em outras palavras, Go para ser bem escrito, é importante compreender as suas propriedades e expressões idiomáticas. Também é importante conhecer as convenções estabelecidas para programação em Go, tais como nomes, formatação, estruturação do programa, e assim por diante, de modo que os programas que escreva sejam mais fácil para outros programadores Go entenderem.

Este documento dá dicas para escrever código claro e idiomático. Ele aumenta a especificação da linguagem , do passeio em Go , e Como escrever Código Go, todos os quais devem ser lidos primeiro.

Exemplos

Os fontes de pacotes Go destinam-se a não servir apenas como a biblioteca de núcleo, mas também como exemplos de como a usar a linguagem. Além disso, muitos dos pacotes contêm trabalho, exemplos embutidos ​​que podem ser executados diretamente do site golang.org, como este (se necessário, clique sobre a palavra "example" para abri-lo). Se você tem uma pergunta sobre como abordar um problema ou como algo pode ser implementado, a documentação, o código e os exemplos na biblioteca pode fornecer respostas, idéias e conceitos.

Formatação

Problemas de formatação são os mais controversos mas menos consequentes. As pessoas podem se adaptar a diferentes estilos de formatação mas é melhor se eles não existirem, e menos tempo é dedicado ao tema se todo mundo adere ao mesmo estilo. O problema é a forma de abordar esta utopia sem um longo guia de estilo prescritivo.

Com Go tomamos uma incomum perspectiva de deixar a máquina cuidar da maioria dos problemas de formatação. O programa gofmt (também disponível como go fmt, que opera no nível do pacote ao invés de nível do arquivo de origem) lê um programa Go e emite a fonte em um estilo padrão de recuo e alinhamento vertical, retenção e se necessário reformatação comentários. Se você quiser saber como lidar com algum novo layout, execute gofmt, se a resposta não parecer boa, reorganize seu programa (ou relate um bug sobre gofmt), não trabalhe em torno dele.

Como um exemplo, não há necessidade de gastar tempo tabulando os comentários sobre os campos de uma estrutura. gofmt irá fazer isso por você. dada a declaração

type T struct {
    name string // nome do objeto
    value int // este é o valor
}

gofmt irá alinhar as colunas:

type T struct {
    name    string // nome do objeto
    value   int    // este é o valor
}

Todo o código Go nos pacotes padrão foi formatado com gofmt.

Alguns detalhes de formatação permanecem. Muito resumidamente:

Recuo
Usamos tabs para recuo e gofmt emite-os por padrão. Use espaços apenas se for preciso.
Comprimento da linha
Go não tem limite para o comprimento da linha. Não se preocupe com um cartão perfurado transbordando. Se uma linha ficar muito longa, quebre-a e dê um recuo (tab) extra.
Parênteses
Go precisa de menos parênteses que C e Java: estruturas de controle (if, for, switch) não tem parênteses na sua sintaxe. Além disso, a hierarquia da precedência do operador é menor e mais clara, de modo
x<<8 + y<<16
significa que o espaçamento implica, ao contrário de outras linguagens.

Comentários

Go fornece blocos de comentários no estilo C/* */ ou comentários de linha no estilo C++ //. Comentários de linha são a norma; blocos de comentários aparecem principalmente como comentários de pacotes, mas são úteis dentro de uma expressão ou para desativar grandes trechos de código.

O programa — e web-server — godoc processa o códigos-fonte Go para extrair a documentação sobre o conteúdo do pacote. Comentários que aparecem antes das declarações de nível superior, sem novas linhas de separação, são extraídos juntamente com a declaração para servir como texto explicativo para o item. A natureza e o estilo destes comentários determina a qualidade da documentação que godoc produzirá.

Cada pacote deve ter um pacote comentário, um bloco comentado que precede a cláusula do pacote. Para pacotes de arquivos múltiplos, o comentário do pacote só precisa se apresentar em um arquivo, e vai aparecer como um todo. O comentário embalagem deve apresentar o pacote e fornecer informações relevantes para o pacote como um todo. Ele será exibido pela primeira vez na página godoc e deve definir-se a documentação detalhada que se segue.

/*
pacote Regexp implementa uma biblioteca simples para expressões regulares.

A sintaxe das expressões regulares aceitas é:

    regexp:
        concatenation { '|' concatenation }
    concatenation:
        { closure }
    closure:
        term [ '*' | '+' | '?' ]
    term:
        '^'
        '$'
        '.'
        character
        '[' [ '^' ] character-ranges ']'
        '(' regexp ')'
*/
package regexp

Se o pacote é simples, o comentário pacote pode ser breve.

// Caminho do pacote implementa rotinas de utilidade para
// manipular os caminhos de nome de arquivo separado por barras.

Comentários não precisam de formatação extra, como banners de estrelas. A saída gerada não pode mesmo ser apresentado em uma fonte de largura fixa, por isso, não dependem em espaçamento de alinhamento-godoc, já que gofmt cuida disso. Os comentários são interpretados em texto simples, de modo que HTML ou outras anotações como _this_ serão reproduzidas textualmente e não podem ser utilizadas. Um ajuste que godoc faz é exibir texto recuado em uma fonte de largura fixa, adequada para trechos do programa. O comentário de pacotes para o fmt usa isso para um bom efeito.

Dependendo do contexto, godoc pode até não reformatar os comentários, por isso certifique-se de olhar bem para cima: usar ortografia, pontuação e estrutura de sentença, quebrar as linhas longas, e assim por diante.

Dentro de um pacote, qualquer comentário que precede imediatamente uma declaração de nível superior serve como um doc comentário para essa declaração. Cada nome exportado (capitalizados) de um programa deve ter um comentário doc.

Comentários de documentação trabalham melhores frases completas, que permitem uma ampla variedade de apresentações automatizados. A primeira frase deve ser um resumo de uma frase que inicia-se com o nome que está sendo declarado.

// Compilar analisa uma expressão regular e retorna, se bem sucedida, uma Regexp
// Objeto que pode ser utilizado para combinar contra texto.
função Compilar (string str) (regexp * Regexp, err erro) {

Se o nome começa sempre com comentário, a saída do godoc pode ser útil para ser executado através do grep. Imagine que você não consegue lembrar o nome de "compilação", mas estava procurando a função de análise de expressões regulares, de modo que você executou o comando,

$ godoc regexp | grep parse

Se todos os comentários doc no pacote começassem com, "Esta função ...", grep não iria ajudá-lo a lembrar o nome. Mas porque o pacote começa cada doc comentário com o nome, você veria algo como isso, que recorda a palavra que você está procurando.

$ godoc regexp | grep parse
    Compilar analisa uma expressão regular e retorna, se bem sucedida, uma Regexp
    analisada. Ele simplifica a inicialização segura de variáveis ​​globais filtrando
    o que não pode ser analisado. Ele simplifica a inicialização segura de variáveis ​​globais
$

A sintaxe de declaração do Go permite agrupamento de declarações. Um único comentário doc pode introduzir um grupo de constantes ou variáveis ​​relacionadas. Toda a declaração é apresentada, tal comentário muitas vezes pode ser superficial.

// Os códigos de erro retornados por falhas para analisar uma expressão.
var (
    ErrInternal      = errors.New("regexp: internal error")
    ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
    ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
    ...
)

Mesmo para nomes particulares, agrupamento também pode indicar relações entre os itens, como o fato de que um conjunto de variáveis ​​é protegido por um mutex.

var (
    countLock   sync.Mutex
    inputCount  uint32
    outputCount uint32
    errorCount  uint32
)

Nomes

Eles até têm efeito semântico: a visibilidade de um nome fora de um pacote é determinada pelo fato de seu primeiro caractere ser maiúsculo. Portanto, vale a pena gastar um pouco de tempo falando sobre convenções de nomenclatura em programas Go.

Nome de pacotes

Quando um pacote é importado, o nome do pacote se torna uma referencia para acessar o conteúdo. Depois de importado, como mostrado abaixo:

import "bytes"

O pacote importado por exemplo trata sobre bytes (Buffer). É útil se todos que usam o pacote puderem usar o mesmo nome para se referir ao seu conteúdo, o que implica que o nome do pacote deve ser bom: curto, conciso, evocativo. Por convenção, os pacotes recebem nomes em minúsculas e de uma só palavra, não deve haver necessidade de underscores ou uso de camel case. Cuidado brevidade, já que todo mundo usando seu pacote estará digitando esse nome. E não se preocupe com colisões a priori. O nome do pacote é apenas o nome padrão para importações, ele não precisa ser único em todo o código-fonte e, no caso raro de uma colisão, o pacote de importação pode escolher um nome diferente para ser usado localmente. Em qualquer caso, a confusão é rara porque o nome do arquivo na importação determina apenas qual pacote está sendo usado.

Outra convenção é o nome do pacote ter como base seu diretório raiz, por exemplo o pacote que está em /encoding/base64 é importado como "encoding/base64" porém tem como nome base64 e não encoding_base64 ou encodingBase64.

O importador de um pacote usará o nome para se referir ao seu conteúdo, portanto, os nomes exportados no pacote podem usar esse fato para evitar colisões. (Não use a notação import ., o que pode simplificar os testes que devem ser executados fora do pacote que eles estão testando, mas devem ser evitados.) Por exemplo, o tipo de leitor de buffer no pacote bufio é chamado Reader, não BufReader, porque os usuários o vêem como bufio.Reader, que é um nome claro e conciso. Além disso, como as entidades importadas são sempre endereçadas com o nome do pacote, o bufio.Reader não entra em conflito com o io.Reader. Da mesma forma, a função para criar novas instâncias de ring.Ring - que é a definição de um construtor no Go - normalmente seria chamada NewRing, mas como Ring é o único tipo exportado pelo pacote, e como o pacote é chamado de ring, é chamado apenas de New, que os clientes da embalagem vêem como ring.New. Use a estrutura de pacotes para ajudá-lo a escolher bons nomes.

Outro exemplo simples é once.Do. O once.Do(setup) é legível e não precisa escrever once.DoOrWaitUntilDone(setup). Nomes grandes não fazem com que sejam mais legíveis, um comentário útil pode ser muito melhor do que nomes enormes.

Getters

Go não provê suporte automático para Getters e Setters. Não tem nada errado em fazer seus getters e setters, geralmente é o mais apropriado, entretanto não é idiomático e nem necessário colocar Get no nome do getter. Se você tiver um campo chamado owner (letra minúscula não é exportado) o getter dele deve ser chamado de Owner (letra maiúscula é exportado), não GetOwner. O uso de letra maiúscula mostra qual seria o método para cada campo. O setter, se necessário, deve ser chamado de SetOwner. Os dois nomes são bem legíveis na prática:

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

Nomes de Interfaces

Por convenção, as interfaces de um método são nomeadas pelo nome do método mais um sufixo -er ou uma modificação semelhante para construir um substantivo de agente: Reader, Writer, Formatter, CloseNotifier etc.

Há vários desses nomes e é uma boa prática honrá-los e também as funções que eles referenciam. Write, Close, Flush, String e assim por diante tem assinaturas canônicas e significativas. Para evitar confusão, não dê ao seu método um desses nomes, a menos que ele tenha a mesma assinatura e significado. Por outro lado, se o seu tipo implementar um método com o mesmo significado que um método em um tipo conhecido, forneça o mesmo nome e assinatura, chame seu método que utiliza Strings de string-converter e não ToString

Camel Case

Finalmente, a convenção em Go é o uso de camelCase ou CamelCase e não o uso de underscores para nomes compostos.