One place for hosting & domains

      Hreflang Tags: Your Gateway to International SEO


      Continually working to optimize your website for search engine visibility will ensure that new users can find your website on the web. There are a range of techniques you can use to improve your website’s SEO rankings for a national audience, however when trying to target audiences in multiple countries or visitors who speak more than one language, you’ll need to follow a few additional rules — one of which involves adding hreflang tags to your website.

      Search engines read hreflang tags to ensure that your pages are indexed correctly for a defined international audience, and that those users are directed to the correct versions of your site. Fortunately, there are a handful of relatively simple, easy methods you can use to insert and leverage these attributes on your website.

      In this post, we’ll introduce you to hreflang tags and explain why they’re important. Then we’ll walk you through how you can implement them on your website. Let’s jump in!

      An Introduction to Hreflang Tags

      First introduced by Google in 2011, the hreflang attribute specifies the language of the content on a page.

      You can use hreflang tags to target specific countries. They are handy for websites offering content in multiple languages.

      Hreflang tags are added to the <head> section of your web pages’ HTML code. Each tag should specify the language and country for a particular page.

      For instance, the tags might look similar to the following:

      <link rel="alternate" hreflang="x-default" href="http://example.com/">
      <link rel="alternate" hreflang="en" href="http://example.com/en/">
      <link rel="alternate" hreflang="de" href="http://example.com/de/">

      In the above example, the first line is the default page for users who don’t speak any of the languages specified. The second and third lines are for English and German speakers, respectively. The hreflang attribute specifies the language, and the href attribute specifies the URL.

      It’s important to note that hreflang tags are only used by search engines — they won’t be visible to users. Furthermore, hreflang tags are just one type of tag that can improve your website’s SEO and User Experience (UX). Other common tags include title tags and meta descriptions.

      Also, keep in mind that hreflang tags and canonical tags are not the same. A canonical tag is an HTML element that tells search engines which version of a page to index.

      A hreflang tag, on the other hand, tells search engines which version of a page to serve to users in different countries. Canonical tags solve duplicate content issues. By contrast, hreflang tags ensure that users who speak different languages are served the correct page versions.

      Why Hreflang Tags Are Important

      Hreflang tags are important for a handful of reasons. They affect both the UX and SEO of your website.

      Benefits of Using Hreflang Tags

      • Ensure that your pages are indexed correctly.
      • Direct users to the correct versions of your site.
      • Lead to higher traffic levels and more conversions.
      • Organize your website.
      • Localize your content for global users.
      • Prevent competition between alternate web pages.

      In addition, hreflang tags can improve your Click-Through Rate (CTR) from Search Engine Result Pages (SERPs). Users who see your site is available in their languages are more likely to click on it. This can lead to higher traffic levels and, ultimately, more conversions.

      How to Use Hreflang Tags (3 Technical Methods)

      There are three main methods for implementing the hreflang attribute on your website. Below, we’ll walk you through each one.

      However, regardless of your chosen method, it’s important to understand three basic elements of hreflang tags. First, the language attribute must be in a two-letter country code known as the ISO 639-1 format. ISO is short for International Organization for Standardization. This value consists of one language, and can be combined with an (optional) region.

      You can use the ISO 3166-1 region codes to specify a region. It’s important not to get the two confused or use them interchangeably. For example, the code for the Greek language is “el”, but the code for the Greece region is “gr”.

      The second rule is that each URL needs to have return links pointing to the canonical versions. For instance, if you have 40 languages, you would have hreflang links for 40 URLs.

      Finally, you need self links for your hreflang tag implementation to work. This means that each language version must also list itself using a self-referential hreflang tag, which the page points back to itself.

      Now, here are three methods for using hreflang tags!

      1. Use HTML Tags in <head> Sections

      As we mentioned earlier, one of the ways to implement hreflang tags on your website is to insert them in HTML tags. This is often the quickest and easiest method.

      However, this process can be time-consuming if you have a long list of languages. You would need to link each variation to every other variation. Additionally, WordPress would have to make multiple database calls to generate these links.

      Ultimately, this could slow down your site. Therefore, if you have a larger website or want to create a long list of languages, you might want to use the sitemap method instead (see Method 3).

      To use this HTML tag method, you must insert your hreflang tags into the <head> section of each of your pages. For instance, if you wanted to add English and Spanish versions for the United States version of your site, you would add the following code:

      <link rel="alternate" hreflang="x-default" href="http://example.com/">
      <link rel="alternate" hreflang="en" href="http://example.com/en/">
      <link rel="alternate" hreflang="es" href="http://example.com/de/">

      In the above example, the first line refers to the default page. The second and third are for English and Spanish speakers.

      2. Insert Hreflang Tags in Your HTTP Headers

      If you want to add hreflang tags in non-HTML pages, such as PDFs, you won’t have HTML code to place the tags in. When this is the case, you can use your HTTP headers instead.

      The code would look something like the following:

      <http://example.pdf>; rel="alternate";hreflang="x-default",
      <http:/example.pdf>; rel="alternate";hreflang="en",
      <http://example.pdf>; rel="alternate";hreflang="es",
      <http://example.pdf>; rel="alternate";hreflang="de"

      In this example, you’re adding variants for English, Spanish, and German. Each of the respective versions must be placed in the headers of each PDF file.

      Get Content Delivered Straight to Your Inbox

      Subscribe to our blog and receive great content just like this delivered straight to your inbox.

      3. Add Hreflang Tags to Your Sitemap

      The third method for implementing hreflang tags is using XML sitemap markup. This approach will let you add the hreflang attributes for all your site’s pages in one place.

      It can also help you avoid slowing down your page loading speed (which might happen if you place the tags in the head section of the pages). Plus, changing a sitemap can be significantly easier than modifying each page’s <head> tag.

      The sitemap method is similar to the HTML <head> tag method, except the xhtml:link attribute adds the hreflang annotations to each URL. Following the xhtml:link attribute at the front of your URL, you would add the alternative page versions, so your markup would look similar to the following:

      <url>
      <loc>https://example.com/link</loc>
      <xhtml:link rel=”alternate” hreflang=”en-us” href=”x-default”
      <xhtml:link rel=”alternate” hreflang=”en” href=”https://example.com/link/” />
      <xhtml:link rel=”alternate” hreflang=”es” href=”https://example.com/enlance/” />

      Here, you’ll see that each URL has a hreflang attribute and return links to the other URLs. A separate <url> element should be created for every URL. Each element must include a <loc> that indicates the page URL. The URLs also need a <xhtml:link rel=”alternate” hreflang=”supported_language-code”> element that lists each alternative version of the page.

      You can add all of the necessary tags to one file. While the order of the elements doesn’t matter, we recommend keeping them uniform, because this layout will make it easier to check for mistakes. You can submit your new sitemap to Google Search Console when you’re done.

      Tools That Generate Hreflang Tags Automatically

      The time it takes to generate and implement your hreflang tags can vary depending on how many versions you want to create and which method you use. However, a handful of tools can simplify and speed up the process. Let’s take a look at some of the most popular ones!

      Weglot Translate Plugin

      Weglot is a popular and reliable translation tool that can add hreflang Google tags and markup to your website:

      The Weglot Translate WordPress plugin

      Weglot can be a helpful solution if you’re a beginner and unfamiliar with working with code. It automatically identifies href tags in your code during translation, and changes the page header links.

      Hreflang Checker

      It’s crucial to always double-check your hreflang tags to ensure that they’re working correctly after you’ve placed them. The Hreflang Checker tool provided by Weglot can help simplify this process:

      The Hreflang Checker tool

      To use it, just copy and paste the URL that you want to check into the text field (make sure to include “http://” or “https://”) and select a search engine bot to emulate. Then click on the Test URL button. It will display a search results page showing your tags’ status.

      XML Sitemap Generator

      If you want to implement hreflang tags using the sitemap method, you can utilize the Hreflang XML Sitemap Generator Tool. It was created by Erudite, a digital marketing agency:

      The Erudite Hreflang Sitemap tool

      After creating an account using your email address, simply tell the tool where to send your sitemap and upload your CSV file, including a column for each language. Then Erudite’s tool will automatically generate an XML sitemap.

      Hreflang Tags Generator

      If you need help generating the link elements for your hreflang tags, you can use the Hreflang Tags Generator:

      the Hreflang Tags Generator tool

      This tool, created by Aleyda Solis, can streamline creating tags for your multi-language or multi-country website. You can generate these tags by either adding the (up to 50) URLs to tag in the given form, or uploading them via a CSV file. Again, you’ll need to make sure that there is one column for the URLs.

      Ahrefs Google Sheets Template

      Another tool that you can use is the Google Sheets template provided by Ahrefs:

      The Hreflang planner Google Sheets template

      Under the Setup tab, select your site’s language-locale (default language), then choose up to four additional variations. For instance, you could pick English as the Default language-locale, followed by Spanish, German, Chinese, and Russian as the alternatives.

      Next, under the URLs tab, you’ll find five columns, each with its own header cells that correspond to the language you chose in the Setup tab. There should also be an X-Default column.

      Now paste the URLs into the respective cells. Then, under the Results tab, you’ll find an auto-generated code for your XML sitemap. You can copy and paste everything in the A column into an XML document and upload it via Google Search Console.

      Tips and Best Practices for Using Hreflang Tags

      Now that you understand the basics of hreflang tags and their implementation, let’s discuss some tips for using them. Below are some key best practices to follow!

      Make Sure the Tags Are Bidirectional

      Hreflang tags operate in pairs, meaning that they are bidirectional. When you add a hreflang tag to an English page pointing to a Spanish version, you also need to ensure that the Spanish variant returns with a hreflang tag pointing to the English version.

      This setup tells search engines the relationship is in agreement, and that you control both pages. If two pages don’t point to each other, Google will ignore the tags.

      Specify the Default Page for Users Who Don’t Speak Any of the Specified Languages

      Specifying the default page for users who don’t speak any of your set languages is important. It will ensure that visitors are directed to the correct version of your site.

      You can do this by adding a tag with the language code “x-default”. It would look something like:

      <link rel=”alternate” hreflang=”x-default” href=”https://example.com/” />

      The default page will be used in situations where Google is unable to extract the language or region for users when it’s not specified or listed. Instead, the x-default page will ask users which language they prefer, then point them to the appropriate alternate version.

      Use Absolute URLs

      Absolute URLs are complete URLs that include the domain name. They are also the preferred type of URL to use with hreflang tags. They are less likely to be affected by changes on your website, and make it easier for search engines to index your pages correctly.

      It’s important to make sure that your hreflang tags contain absolute URLs. In other words, the code should look like “https://example.com/link” rather than “example.com/link”.

      Make Sure Your Hreflang Tags Are Valid and Correctly Formatted

      As we mentioned earlier, the correct ISO language and region codes must be used when creating your hreflang link attributes. Otherwise, you may encounter a message in Google Search Console informing you that your site doesn’t have any hreflang language tags.

      Remember to use the ISO language codes for language attributes and the region codes for geographical locations. For instance, while “kr” is for the region of South Korea, “ko” is the code for the Korean language.

      Keep Your Hreflang Tags Up To Date

      As you continue adding content and pages to your website, keeping up with your hreflang tags becomes more critical.

      Let’s say you add a new domain for a particular country. Then you’ll need to add the appropriate hreflang tags to your existing pages, and check to ensure that they point to the new domain.

      The same applies if you delete any language versions of your website. If you remove a language, you’ll need to delete or replace the hreflang tags pointing to it. Pointing to missing or incorrect URLs can hurt both your UX and SEO.

      Monitor Your Website for Errors

      Just as essential as keeping your hreflang tags updated is consistently monitoring your website for errors. This process includes checking your site’s source code to make sure that all necessary tags are present.

      You can use a tool such as Google Search Console to monitor your website more easily. This platform will help you verify whether your pages are being indexed correctly.

      Optimize Your Website for International Audiences

      Using hreflang tags can improve the SEO and UX of your website for international audiences. These attributes can help your site reach users in different countries, and ensure that the correct content is served in their native or preferred languages.

      As we discussed in this article, there are three methods you can use to implement hreflang tags:

      1. Add the attributes to the <head> section of each page.
      2. Place them in the HTTP headers of non-HTML content pages.
      3. Put the tags in your XML sitemap, so that all the attributes are in one place.

      Do you need help optimizing your multilingual website? Check out our DreamHost Pro Services to learn how we can take your site to the next level!

      International SEO Made Easy

      We take the guesswork (and actual work) out of growing your website traffic with SEO.

      shared hosting



      Source link

      Personalizando binários em Go com build tags


      Introdução

      No Go, um build tag, ou uma restrição de compilação, é um identificador adicionado a um pedaço de código que determina quando o arquivo deve ser incluído em um pacote durante o processo de build. Isso permite que você compile diferentes versões de seu aplicativo em Go a partir do mesmo código fonte e para alternar entre eles de maneira rápida e organizada. Muitos desenvolvedores usam os build tags (sinalizadores de compilação) para melhorar o fluxo de trabalho da compilação de aplicativos compatíveis entre plataformas, tais como os programas que necessitam de mudanças no código para explicar as variações entre diferentes sistemas operacionais. Os build tags também são usados para testes de integração, permitindo que você alterne rapidamente entre o código integrado e o código com um serviço fictício ou stub e para diferenciar os níveis dos conjuntos de recursos dentro de um aplicativo.

      A título de exemplo, vamos considerar o problema dos diferentes conjuntos de recursos do cliente. Ao escrever alguns aplicativos, você pode querer controlar quais recursos incluir no binário, como um aplicativo que oferece níveis Free (Livre), Pro (Profissional) e Enterprise (Empresarial). À medida que o cliente aumenta seu nível de assinatura nesses aplicativos, mais recursos se tornam desbloqueados e disponíveis. Para resolver esse problema, você poderia manter projetos separados e tentar mantê-los em sincronia uns com os outros através do uso de instruções de import. Embora essa abordagem iria funcionar,com o tempo ela se tornaria entediante e propensa a erros. Uma abordagem alternativa seria usar os build tags (sinalizadores de compilação).

      Neste artigo, você usará os build tags no Go para gerar diferentes binários executáveis que oferecem conjuntos de recursos Free, Pro e Enterprise de um aplicativo exemplo. Cada binário terá um conjunto diferente de recursos disponíveis, com a versão Free sendo a padrão.

      Pré-requisitos

      Para seguir o exemplo neste artigo, será necessário:

      Compilando a versão Free

      Vamos começar compilando a versão Free do aplicativo, uma vez que ela será a versão padrão durante a execução do go build, sem quaisquer build tags. Mais tarde, usaremos os build tags para adicionar seletivamente outras partes ao nosso programa.

      No diretório src, crie uma pasta com o nome do seu aplicativo. Este tutorial usará o nome app:

      Mova para esta pasta:

      Em seguida, crie um novo arquivo de texto, chamado main.go, no editor de texto de sua preferência:

      Agora, vamos definir a versão Free do aplicativo. Adicione o conteúdo a seguir ao main.go:

      main.go

      package main
      
      import "fmt"
      
      var features = []string{
        "Free Feature #1",
        "Free Feature #2",
      }
      
      func main() {
        for _, f := range features {
          fmt.Println(">", f)
        }
      }
      

      Neste arquivo, criamos um programa que declara uma fatia chamada features, que contém duas strings que representam os recursos de nosso aplicativo Free. A função main() no aplicativo usa um loop for para o range (intervalo) dentro da fatia de features e depois imprime todos os recursos disponíveis na tela.

      Salve e saia do arquivo. Agora que este arquivo está salvo, não precisaremos mais editá-lo pelo resto do artigo. Em vez disso, usaremos os build tags para alterar as características dos binários que vamos compilar a partir dele.

      Compile e execute o programa:

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2

      O programa imprimiu nossos nossos dois recursos gratuitos, completando a versão Free do nosso aplicativo.

      Até agora, você criou um aplicativo que tem um conjunto de características bem básicas. Em seguida, você irá criar uma maneira de adicionar mais recursos no aplicativo no momento da compilação.

      Até agora, evitamos fazer alterações no main.go, simulando um ambiente de produção comum no qual o código precisa ser adicionado, sem alterar e possivelmente quebrar o código principal. Como não podemos editar o arquivo main.go, precisaremos usar outro mecanismo para injetar mais recursos na fatia de features usando os build tags.

      Vamos criar um novo arquivo chamado pro.go que usará uma função init() para acrescentar mais recursos na fatia de features:

      Assim que o editor abrir o arquivo, adicione as seguintes linhas:

      pro.go

      package main
      
      func init() {
        features = append(features,
          "Pro Feature #1",
          "Pro Feature #2",
        )
      }
      

      Neste código, usamos o init() para executar o código antes da função main() do nosso aplicativo, seguido pelo append() para adicionar os recursos Pro à fatia features. Salve e saia do arquivo.

      Compile e execute o aplicativo usando o go build:

      Como agora existem dois arquivos em nosso diretório atual (pro.go e main.go), o go build criará um binário de ambos. Execute este binário:

      Isso dará a você o seguinte conjunto de recursos:

      Output

      > Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

      Agora, o aplicativo agora inclui tanto os recursos da versão Pro como os recursos da Free. No entanto, isso não é desejável: uma vez que não há distinção entre as versões, a versão Free agora inclui os recursos que deveriam estar disponíveis apenas na versão Pro. Para corrigir isso, você poderia incluir mais códigos para gerenciar os diferentes níveis do aplicativo ou usar os build tags para dizer à cadeia de ferramentas Go quais arquivos .go compilar e quais ignorar. Vamos adicionar os build tags no próximo passo.

      Agora, é possível usar os build tags para distinguir a versão Pro do seu aplicativo da versão Free.

      Vamos começar examinando como se parece um build tag:

      // +build tag_name
      

      Ao colocar essa linha de código como a primeira linha do seu pacote e substituir o tag_name pelo nome do seu build tag, você irá sinalizar esse pacote como um código que pode ser incluído seletivamente no binário final. Vamos ver como isso funciona na prática, adicionando um build tag ao arquivo pro.go para dizer ao comando go build ignorá-lo, a menos que o tag seja especificado. Abra o arquivo no seu editor de texto:

      Então, adicione a linha destacada a seguir:

      pro.go

      // +build pro
      
      package main
      
      func init() {
        features = append(features,
          "Pro Feature #1",
          "Pro Feature #2",
        )
      }
      

      No topo do arquivo pro.go, adicionamos // +build pro, seguido de uma nova linha em branco. Esta essa nova linha no final é necessária, caso contrário o Go interpreta o comando como um comentário. As declarações de build tag também devem estar na parte superior do arquivo .go. Nada, nem mesmo comentários, pode estar acima dos build tags.

      A declaração +build diz ao comando go build que este não é um comentário, mas sim um build tag. A segunda parte é o sinalizador pro. Ao adicionar esse sinalizador na parte superior do arquivo pro.go, o comando go build agora só incluirá o arquivo pro.go se o sinalizador pro estiver presente.

      Compile e execute o aplicativo novamente:

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Como o arquivo pro.go exige que um sinalizador pro esteja presente, o arquivo é ignorado e o aplicativo compila sem ele.

      Ao executar o comando go build, podemos usar o sinalizador -tags para incluir, por condição, o código na fonte compilada, adicionando o sinalizador propriamente dito como um argumento. Vamos fazer isso para o sinalizador pro:

      Isso irá mostrar o seguinte:

      Output

      > Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

      Agora, vamos obter recursos extra quando compilarmos o aplicativo usando build tag pro.

      Não haverá problemas nisso caso houver apenas duas versões, mas as coisas ficam complicadas quando você adicionar mais sinalizadores. Para adicionar na versão Enterprise de nosso aplicativo no próximo passo, usaremos vários build tags juntos com a lógica booleana.

      Quando há vários build tags em um pacote Go, eles interagem entre si usando a Lógica booleana. Para demonstrar isso, adicionaremos o nível Enterprise do nosso aplicativo usando os sinalizadores pro e enterprise.

      Para compilar um binário Enterprise, precisaremos incluir os recursos padrão, os recursos de nível Pro e um novo conjunto de recursos para o Enterprise. Primeiro, abra um editor e crie um novo arquivo, o enterprise.go, que adicionará os novos recursos de Enterprise:

      O conteúdo do enterprise.go ficará quase idêntico ao pro.go, mas terá novos recursos. Adicione as seguintes linhas ao arquivo:

      enterprise.go

      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Salve e saia do arquivo.

      No momento, o arquivo enterprise.go não possui nenhum build tag e, como você aprendeu ao adicionar recursos no pro.go, isto significa que esses recursos serão adicionados à versão Free durante a execução do go.build. Para o pro.go, você adicionou // + build pro e uma nova linha na parte superior do arquivo para dizer ao go build que ele deve ser incluído somente quando -tags pro for usada. Nessa situação, você precisa apenas de um build tag para atingir o objetivo. No entanto, ao adicionar os novos recursos de Enterprise, você primeiro deve ter os recursos Pro.

      Vamos primeiro adicionar o suporte para build tag pro ao enterprise.go. Abra o arquivo com seu editor de texto:

      Em seguida, adicione o build tag antes da declaração package main e certifique-se de incluir uma nova linha após o build tag:

      enterprise.go

      // +build pro
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Salve e saia do arquivo.

      Compile e execute o aplicativo sem quaisquer sinalizadores:

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Os recursos Enterprise não vão mais aparecer na versão Free. Agora, vamos adicionar o build tag pro, compilar e executar o aplicativo novamente:

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

      Isso ainda não é exatamente o que precisamos: os recursos da versão Enterprise agora aparecem quando tentamos compilar a versão Pro. Para resolver isso, precisamos usar outro build tag. No entanto, ao contrário do sinalizador pro, precisamos agora garantir que os recursos pro e enterprise estejam disponíveis.

      O sistema de compilação Go é responsável por essa situação, permitindo o uso de uma lógica básica booleana no sistema de build tags.

      Vamos abrir o enterprise.go novamente:

      Adicione outro build tag, enterprise, na mesma linha do identificador pro:

      enterprise.go

      // +build pro enterprise
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Salve e feche o arquivo.

      Agora, vamos compilar e executar o aplicativo com o novo build tag enterprise.

      • go build -tags enterprise
      • ./app

      Isso resultará no seguinte:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2

      Agora, perdemos os recursos Pro. Isso acontece porque quando colocarmos vários build tags na mesma linha em um arquivo .go, o go build os interpreta como se estivesse usando uma lógica OR. Com a adição da linha // + build pro enterprise, o arquivo enterprise.go será compilado caso tanto o build tag pro quanto o enterprise estiverem presentes. Em vez disso, precisamos configurar os build tags corretamente para exigir ambos e usar a lógica AND.

      Em vez de colocar ambos sinalizadores na mesma linha, se os colocarmos em linhas separadas, o go build irá, então, interpretar esses identificadores usando a lógica AND.

      Abra o enterprise.go novamente e vamos separar os build tags em várias linhas.

      enterprise.go

      // +build pro
      // +build enterprise
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Agora, compile e execute o aplicativo com o novo build tag enterprise.

      • go build -tags enterprise
      • ./app

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Ainda não chegamos lá: como uma instrução AND exige que ambos os elementos sejam considerados true, precisamos usar os build tags pro e enterprise juntos.

      Vamos tentar novamente:

      • go build -tags "enterprise pro"
      • ./app

      Você receberá o seguinte resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

      Agora, nosso aplicativo pode ser compilado a partir da mesma árvore de várias maneiras, desbloqueando os recursos do aplicativo corretamente.

      Neste exemplo, usamos um novo sinalizador // + build para significar uma lógica AND, mas existem maneiras alternativas de representar a lógica booleana com os build tags. A tabela a seguir contém alguns exemplos de formatação sintática para build tags, junto com suas equivalentes booleanas:

      Sintaxe do build tagAmostra de build tagInstrução booleana
      Elementos separados por espaço// +build pro enterprisepro OU enterprise
      Elementos separados por vírgula// +build pro,enterprisepro E enterprise
      Elementos com ponto de exclamação// +build ! proNÃO é pro

      Conclusão

      Neste tutorial, você usou build tags para permitir que você controle qual de seus códigos será compilado no binário. Primeiro, você declarou os build tags e os usou com o go build; depois, combinou vários identificadores com a lógica booleana. Em seguida, você compilou um programa que representava os diferentes conjuntos de recursos de uma versão Free, Pro e Enterprise, mostrando o poderoso nível de controle sobre o seu projeto que os build tags podem dar a você.

      Se quiser aprender mais sobre os build tags, consulte a documentação do Golang sobre o assunto, ou continue a explorar nossa série de artigos sobre Como codificar em Go.



      Source link

      Como usar tags struct em Go


      Introdução

      As estruturas, ou structs, são usadas para coletar vários fragmentos de informações em uma unidade. Essas coletas de informações são usadas para descrever conceitos de nível superior, como um Address composto de uma Street, City, State e PostalCode. Ao ler essas informações a partir de sistemas como bancos de dados, ou APIs, você pode usar tags struct para controlar como essa informação é atribuída aos campos de uma struct. As tags struct são pequenos fragmentos de metadados, anexados aos campos de uma struct – que fornecem instruções para outro código em Go – que funciona com a struct.

      Qual é a aparência de uma tag struct?

      As tags struct do Go são anotações que aparecem após o tipo, em uma declaração struct em Go. Cada tag é composta por strings curtas, associadas a um valor correspondente.

      Uma tag struct se parece com isso, com a tag deslocada com caracteres de crase (backtick) “”`:

      type User struct {
          Name string `example:"name"`
      }
      

      Assim, outro código em Go consegue examinar essas structs e extrair os valores atribuídos a chaves específicas que ele solicita. As tags struct não têm efeito sobre a operação do seu código sem algum outro código que as examine.

      Teste este exemplo, para ver como as tags de struct se parecem e para ver que, sem o código de outro pacote, elas não têm efeito.

      package main
      
      import "fmt"
      
      type User struct {
          Name string `example:"name"`
      }
      
      func (u *User) String() string {
          return fmt.Sprintf("Hi! My name is %s", u.Name)
      }
      
      func main() {
          u := &User{
              Name: "Sammy",
          }
      
          fmt.Println(u)
      }
      

      Isso resultará em:

      Output

      Hi! My name is Sammy

      Esse exemplo define um tipo User com um campo Name. O campo Name recebeu uma tag struct do example:"name". Teríamos que nos referir a essa tag específica na conversa como “exemplo de tag de struct”, pois ela usa a palavra “exemplo” como sua chave. A tag de struct example tem o valor "name" no campo Name. No tipo User, também definimos o método String() necessário através da interface fmt.Stringer. Isso será chamado automaticamente quando enviarmos o tipo para o fmt.Println e nos dará a chance de produzir uma versão bem formatada da nossa struct.

      Dentro do corpo de main, criamos uma nova instância do nosso tipo User e a enviamos para o fmt.Println. Embora a struct tenha um identificador de struct presente, vemos que ela não tem efeito na operação deste código do Go. Ela se comportará exatamente da mesma forma se o identificador da struct não estiver presente.

      Para usar os identificadores de struct para conseguir algo, será necessário que outro código do Go seja escrito para examinar as structs no tempo de execução. A biblioteca padrão tem pacotes que usam identificadores de struct como parte da sua operação. O mais popular deles é o pacote encoding/json.

      Codificando o JSON

      JavaScript Object Notation (JSON) é um formato textual para a codificação de coletas de dados organizados em diferentes chaves de string. É comumente usado para comunicar dados entre programas diferentes, uma vez que o formato é bastante simples, a ponto de haver bibliotecas para decodificá-lo em muitas linguagens diferentes. A seguir, temos um exemplo do JSON:

      {
        "language": "Go",
        "mascot": "Gopher"
      }
      

      Esse objeto JSON contém duas chaves, language e mascot. Depois dessas chaves estão os valores associados. Aqui, a chave language tem um valor de Go e o valor Gopher foi atribuído à chave mascot.

      O codificador JSON na biblioteca padrão usa os identificadores de struct como anotações que indicam ao codificador como você gostaria de nomear seus campos na saída em JSON. Esses mecanismos de codificação e decodificação do JSON podem ser encontrados no pacote encoding/json.

      Experimente este exemplo para ver como JSON está codificado sem os identificadores de struct:

      package main
      
      import (
          "encoding/json"
          "fmt"
          "log"
          "os"
          "time"
      )
      
      type User struct {
          Name          string
          Password      string
          PreferredFish []string
          CreatedAt     time.Time
      }
      
      func main() {
          u := &User{
              Name:      "Sammy the Shark",
              Password:  "fisharegreat",
              CreatedAt: time.Now(),
          }
      
          out, err := json.MarshalIndent(u, "", "  ")
          if err != nil {
              log.Println(err)
              os.Exit(1)
          }
      
          fmt.Println(string(out))
      }
      

      Isso imprimirá o seguinte resultado:

      Output

      { "Name": "Sammy the Shark", "Password": "fisharegreat", "CreatedAt": "2019-09-23T15:50:01.203059-04:00" }

      Definimos uma struct que descreve um usuário com campos, incluindo seu nome, senha e o momento em que o usuário foi criado. Dentro da função main, criamos uma instância desse usuário, fornecendo valores para todos os campos, exceto PreferredFish (Sammy gosta de todos os peixes). Então, enviamos a instância do User para a função json.MarshalIndent. Isso é usado para que possamos ver mais facilmente o resultado do JSON sem usar uma ferramenta de formatação externa. Essa chamada poderia ser substituída por json.Marshal(u) para receber o JSON sem qualquer espaço em branco adicional. Os dois argumentos adicionais para o json.MarshalIndent controlam o prefixo para a saída (que omitimos com a string vazia) e os caracteres que são usados para o recuo, que aqui são dois caracteres de espaço. Quaisquer erros produzido a partir do json.MarshalIndent ficam registrados e o programa se encerra usando o os.Exit(1). Por fim, lançamos o []byte retornado do json.MarshalIndent para uma string e entregamos a string resultante para o fmt.Println, para impressão no terminal.

      Os campos da struct aparecem exatamente como as nomeamos. Esse não é o estilo típico que talvez você espere do JSON, o qual usa o camel casing para os nomes dos campos. [Nota: na convenção Camel-Case, a primeira letra da primeira palavra fica em minúscula e a primeira letra de todas as palavras subsequentes fica em maiúscula]. Neste exemplo, você alterará os nomes do campo para seguir o estilo camel case. Ao executar esse exemplo, você verá que isso não vai funcionar porque os nomes desejados para os campos entram em conflito com as regras do Go sobre nomes de campo exportados.

      package main
      
      import (
          "encoding/json"
          "fmt"
          "log"
          "os"
          "time"
      )
      
      type User struct {
          name          string
          password      string
          preferredFish []string
          createdAt     time.Time
      }
      
      func main() {
          u := &User{
              name:      "Sammy the Shark",
              password:  "fisharegreat",
              createdAt: time.Now(),
          }
      
          out, err := json.MarshalIndent(u, "", "  ")
          if err != nil {
              log.Println(err)
              os.Exit(1)
          }
      
          fmt.Println(string(out))
      }
      

      Isso apresentará a seguinte saída:

      Output

      {}

      Nesta versão, modificamos os nomes dos campos para serem em estilo camel case. Agora, Name passa a ser name, Password a password e, finalmente, CreatedAt passa a ser createdAt. Dentro do corpo de main, alteramos a instanciação de nossa struct para usar esses novos nomes. Então, enviamos a struct para a função json.MarshalIndent como antes. A saída, dessa vez é um objeto JSON vazio, {}.

      Os campos em camel case requerem que o primeiro caractere seja minúsculo. Embora JSON não se importe como você nomeia seus campo, o Go se importa, uma vez que indica a visibilidade do campo fora do pacote. Como o pacote encoding/jason é um pacote separado do pacote main que estamos usando, devemos usar caixa alta para o primeiro caractere, a fim de torná-lo visível para o encoding/json. Neste caso, aparentemente, estaríamos com um impasse. Assim, precisamo encontrar uma maneira de transmitir ao codificador JSON como gostaríamos de nomear esse campo.

      Usando identificadores de struct para controlar a codificação.

      Você pode modificar o exemplo anterior para os campos sejam exportados com a codificação correta, ou seja, com nomes de campo em camel case, anotando cada campo com um identificador de struct. O identificador de struct que o encoding/json reconhece tem uma chave do json e um valor que controla a saída. Colocar a versão dos nomes dos campos em camel case como o valor para a chave json, fará o codificador usar aquele nome. Este exemplo conserta as duas tentativas anteriores:

      package main
      
      import (
          "encoding/json"
          "fmt"
          "log"
          "os"
          "time"
      )
      
      type User struct {
          Name          string    `json:"name"`
          Password      string    `json:"password"`
          PreferredFish []string  `json:"preferredFish"`
          CreatedAt     time.Time `json:"createdAt"`
      }
      
      func main() {
          u := &User{
              Name:      "Sammy the Shark",
              Password:  "fisharegreat",
              CreatedAt: time.Now(),
          }
      
          out, err := json.MarshalIndent(u, "", "  ")
          if err != nil {
              log.Println(err)
              os.Exit(1)
          }
      
          fmt.Println(string(out))
      }
      

      Isso resultará em:

      Output

      { "name": "Sammy the Shark", "password": "fisharegreat", "preferredFish": null, "createdAt": "2019-09-23T18:16:17.57739-04:00" }

      Revertemos os nomes de campo para ficarem visíveis para outros pacotes, usando caixa alta nas primeiras letras de seus respectivos nomes. No entanto, adicionamos desta vez os identificadores de struct na forma do json:"name", onde "name" era o nome que queríamos que o json.MarshalIndent usasse ao imprimir nossa struct como JSON.

      Agora, formatamos nosso JSON corretamente. No entanto, note que os campos para alguns valores foram impressos, embora não tivéssemos definido tais valores. O codificador JSON também pode eliminar esses campos, se você quiser.

      Removendo os campos vazios do JSON

      Mais comumente, queremos suprimir os campos de saída que não estão definidos no JSON. Como todos os tipos em Go tem um “valor zero”, um valor padrão para o qual eles foram definidos, o pacote encoding/json precisa de informações adicionais para conseguir dizer que um dado campo deverá ser considerado como não definido ao assumir esse valor zero. Dentro de parte do valor de qualquer identificador de struct do json, você pode acrescentar um sufixo ao nome que deseja para o seu campo, usando o omitempty. Isso dirá ao codificador JSON que ele deve suprimir a saída desse campo quando ele estiver definido para o valor zero. O exemplo a seguir corrige os exemplos anteriores para não mostrar mais os campos vazios:

      package main
      
      import (
          "encoding/json"
          "fmt"
          "log"
          "os"
          "time"
      )
      
      type User struct {
          Name          string    `json:"name"`
          Password      string    `json:"password"`
          PreferredFish []string  `json:"preferredFish,omitempty"`
          CreatedAt     time.Time `json:"createdAt"`
      }
      
      func main() {
          u := &User{
              Name:      "Sammy the Shark",
              Password:  "fisharegreat",
              CreatedAt: time.Now(),
          }
      
          out, err := json.MarshalIndent(u, "", "  ")
          if err != nil {
              log.Println(err)
              os.Exit(1)
          }
      
          fmt.Println(string(out))
      }
      

      Este exemplo irá mostrar o resultado:

      Output

      { "name": "Sammy the Shark", "password": "fisharegreat", "createdAt": "2019-09-23T18:21:53.863846-04:00" }

      Nós modificamos os exemplos anteriores para que o campo PreferredFish tenha agora o identificador de struct json:"preferredFish,omitempty". A presença do acréscimo ,omitempty faz com que o codificador JSON ignore aquele campo, uma vez que decidimos deixá-lo como não definido. Nos resultados de nossos exemplos anteriores, isso aparecia com valor null.

      Esse resultado ficou muito melhor, mas ainda estamos imprimindo a senha do usuário. O pacote encoding/json proporciona outra maneira de ignorarmos totalmente os campos privados.

      Ignorando os campos privados

      Alguns campos devem ser exportados das structs para que outros pacotes possam interagir corretamente com o tipo. No entanto, esses campos podem ser de natureza confidencial. Assim, em circunstâncias como essas,vamos querer que o codificador JSON ignore totalmente esses campos – mesmo quando ele estiver definido. Para tanto, usamos o valor especial - como o argumento de valor para um identificador de struct do json:.

      Este exemplo corrige o problema da exposição da senha do usuário.

      package main
      
      import (
          "encoding/json"
          "fmt"
          "log"
          "os"
          "time"
      )
      
      type User struct {
          Name      string    `json:"name"`
          Password  string    `json:"-"`
          CreatedAt time.Time `json:"createdAt"`
      }
      
      func main() {
          u := &User{
              Name:      "Sammy the Shark",
              Password:  "fisharegreat",
              CreatedAt: time.Now(),
          }
      
          out, err := json.MarshalIndent(u, "", "  ")
          if err != nil {
              log.Println(err)
              os.Exit(1)
          }
      
          fmt.Println(string(out))
      }
      

      Quando executar o exemplo, verá este resultado:

      Output

      { "name": "Sammy the Shark", "createdAt": "2019-09-23T16:08:21.124481-04:00" }

      A única coisa que mudamos nesse exemplo – em relação aos exemplos anteriores, foi o campo da senha que agora usa o valor especial "-" em seu identificador de struct json:. Constatamos isso no resultado desse exemplo em que o campo password não está mais presente.

      Os recursos ,omitempty e "-" do pacote encoding/json não são padrões. O que um pacote decide fazer com os valores de um identificador de struct depende de sua implementação. Como o pacote encoding/json faz parte da biblioteca padrão, outros pacotes também implementaram esses recursos da mesma forma somente a título de convenção. No entanto, é importante ler a documentação dos pacotes de terceiros que utilizem identificadores de struct, a fim de aprender quais são compatíveis e quais não são.

      Conclusão

      Os identificadores de struct proporcionam um meio poderoso para aumentar a funcionalidade do código que funciona com suas structs. Muitos pacotes da biblioteca padrão e de terceiros oferecem maneiras de personalizar sua operação, usando identificadores de struct. Usá-los de maneira eficaz no seu código propicia esse comportamento de personalização e documenta de maneira sucinta como esses campos são usados para conhecimento dos futuros desenvolvedores.



      Source link