One place for hosting & domains

      тегов

      Настройка бинарных файлов в Go с помощью тегов сборки


      Введение

      В Go тег сборки, или ограничение сборки, — это идентификатор, добавляемый в кусок кода, который определяет, когда файл должен быть включен в пакет в процессе сборки. Это позволяет создавать различные версии вашего приложения Go из одного исходного кода и переключаться между ними в быстрой и организованной манере. Многие разработчики используют теги сборки для упрощения рабочего процесса при сборке кросс-платформенных приложений, например, программ, которые требуют изменений кода для учета различий между разными операционными системами. Теги сборки также используются для тестирования интеграции, позволяя вам быстро переключаться между интегрированным кодом и кодом со службой mock или stub, а также для разделения уровней наборов функций внутри приложения.

      Давайте рассмотрим проблему разделения наборов клиентских функций в качестве примера. При написании некоторых приложений вы можете захотеть контролировать, какие функции включать в бинарный файл, например, при работе с приложением, которое имеет бесплатный, профессиональный и корпоративный уровни. Если пользователь повышает уровень подписки в этих приложениях, все больше функций становятся доступными. Чтобы решить эту проблему, вы можете поддерживать отдельные проекты и пытаться держать их в синхронизированном состоянии через использование оператора import. Хотя этот подход может сработать, со временем он вызовет все больше затруднений и ошибок. Альтернативным способом может быть использование тегов сборки.

      В этой статье вы будете использовать теги сборки в Go для генерации различных исполняемых бинарных файлов, которые предлагают бесплатные, профессиональные и корпоративные наборы функций примера приложения. Каждый из них будет иметь различный набор доступных функций, а по умолчанию будет доступна бесплатная версия.

      Предварительные требования

      Для выполнения примера из этой статьи вам потребуется следующее:

      Сборка бесплатной версии

      Давайте начнем со сборки бесплатной версии приложения, поскольку она будет использоваться по умолчанию при запуске go build без каких-либо тегов сборки. Позднее мы будем использовать теги сборки, чтобы избирательно добавлять другие части нашей программы.

      В директории src создайте папку с именем вашего приложения. В этом обучающем руководстве мы будем использовать app:

      Перейдите в эту папку:

      Затем создайте новый текстовый файл в текстовом редакторе по вашему выбору с именем main.go:

      Теперь мы определим бесплатную версию приложения. Добавьте следующее содержимое в 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)
        }
      }
      

      В этом файле мы создали программу, которая объявляет срез с именем features, который хранит две строки, представляющие собой функции бесплатной версии приложения. Функция main() в приложении использует цикл for для прохождения по срезу features и вывода всех доступных функций на экране.

      Сохраните и закройте файл. Теперь, когда этот файл сохранен, нам больше не нужно будет редактировать его до конца статьи. Вместо этого мы будем использовать теги сборки, чтобы изменять функции бинарных файлов, которые мы будем собирать.

      Выполните сборку и запустите программу:

      Вывод должен выглядеть следующим образом:

      Output

      > Free Feature #1 > Free Feature #2

      Программа вывела на экран две наши бесплатные функции, которые входят в бесплатную версию нашего приложения.

      Итак, сейчас у вас есть приложение с базовым набором функций. Далее вы узнаете, как добавить дополнительные функции в приложение во время сборки.

      Добавление профессиональных функций с помощью команды go build

      До этого мы избегали внесения изменений в main.go, симулируя стандартную рабочую среду, в которой код должен добавляться без изменений и возможного нарушения основного кода. Поскольку мы не можем изменять файл main.go, нам нужно будет использовать другой механизм для введения нового функционала в срез features с помощью тегов сборки.

      Давайте создадим новый файл pro.go, который будет использовать функцию init() для добавления дополнительных функций в срез features:

      После открытия файла в редакторе добавьте следующие строки:

      pro.go

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

      В этом коде мы использовали init() для запуска кода перед функцией main() нашего приложения, а затем append() для добавления профессиональных функций в срез features. Сохраните и закройте файл.

      Скомпилируйте и запустите приложение с помощью команды go build:

      Поскольку в нашей текущей директории есть два файла (pro.go и main.go), go build будет создавать бинарный файл для обоих из них. Запустите этот бинарный файл:

      В результате мы получим следующий набор функций:

      Output

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

      Теперь приложение включает как профессиональные, так и бесплатные функции. Однако это нежелательно, поскольку различия между версиями отсутствуют, а бесплатная версия включает функции, которые должны быть доступны только в профессиональной версии. Чтобы исправить это, вы можете добавить код для управления разными слоями приложения, либо вы можете использовать теги сборки, чтобы сообщить цепочке инструментов Go, какие файлы .go нужно использовать для сборки, а какие игнорировать. Давайте добавим теги сборки в следующем шаге.

      Добавление тегов сборки

      Теперь вы можете использовать теги сборки, чтобы отметить различия между бесплатной и профессиональной версиями.

      Давайте начнем с изучения того, как выглядит тег сборки:

      // +build tag_name
      

      Добавив следующую строку кода в качестве первой строки вашего пакета и заменив tag_name на имя вашего тега сборки, вы пометите этот пакет в качестве кода, который может быть выборочно включен в конечный бинарный файл. Давайте посмотрим это в действии, добавив тег сборки в файл pro.go, чтобы указать команде go build игнорировать его, если тег не указан. Откройте файл в своем текстовом редакторе:

      А затем добавьте следующую выделенную строку:

      pro.go

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

      В верхней части файла pro.go мы добавили //+build pro с чистой новой строкой. Эта последующая строка должна присутствовать обязательно, иначе Go будет интерпретировать это содержимое как комментарий. Объявления тега сборки должны находиться в самой верхней части файла .go. Ничего, даже комментарии, не может быть выше тегов сборки.

      Объявление +build указывает команде go build, что это не комментарий, а тег сборки. Вторая часть — это тег pro. Добавив этот тег в верхней части файла pro.go, команда go build будет включать только файл pro.go только при наличии тега pro.

      Скомпилируйте и снова запустите приложение:

      Вывод должен выглядеть следующим образом:

      Output

      > Free Feature #1 > Free Feature #2

      Поскольку файл pro.go требует наличия тега pro, файл будет игнорироваться, а приложение будет компилироваться без этого файла.

      При запуске команды go build мы можем использовать флаг -tags для условного включения кода в скомпилированный источник, добавив тег как аргумент. Давайте сделаем это для тега pro:

      В результате вы получите следующий вывод:

      Output

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

      Теперь мы получим только дополнительные функции, когда будем выполнять сборку приложения, используя тег сборки pro.

      Это нормально, если у вас есть только две версии, но при добавлении дополнительных тегов все усложняется. Чтобы добавить корпоративную версию вашего приложения в следующем шаге, мы будем использовать несколько тегов сборки, объединенных булевой логикой.

      Булева логика для тегов сборки

      Когда в пакете Go есть несколько тегов сборки, теги взаимодействуют друг с другом с помощью булевой логики. Чтобы продемонстрировать это, мы добавим корпоративный уровень вашего приложения, используя тег pro и тег enterprise.

      Чтобы создать бинарный файл для корпоративной версии, нам потребуется включить функции по умолчанию, функции профессионального уровня и новый набор функций для корпоративного уровня. Сначала откройте редактор и создайте новый файл enterprise.go, который будет добавлять новые функции корпоративного уровня:

      Содержимое файла enterprise.go будет выглядеть почти так же, как и в pro.go, но будет содержать новые функции. Добавьте в файл следующие строки:

      enterprise.go

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

      Сохраните и закройте файл.

      В настоящее время в файле enterprise.go нет тегов сборки, а как вы узнали при добавлении pro.go, это означает, что эти функции будут добавляться в бесплатную версию при исполнении go.build. Для pro.go вы добавили //+build pro и новую строку сверху файла, чтобы указать go build, что данный файл следует включать только при использовании -tags pro. В этой ситуации вам потребуется только один тег сборки для достижения цели. Однако при добавлении новых корпоративных функций у вас должны быть в наличии функции профессионального уровня.

      Давайте добавим поддержку тега сборки pro в файл enterprise.go. Откройте этот файл в текстовом редакторе:

      Далее добавьте тег сборки перед основным объявлением пакета main и обязательно добавьте новую строку после тега сборки:

      enterprise.go

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

      Сохраните и закройте файл.

      Скомпилируйте и запустите приложение без каких-либо тегов:

      Вывод должен выглядеть следующим образом:

      Output

      > Free Feature #1 > Free Feature #2

      Функции корпоративной версии больше не отображаются в бесплатной версии. Теперь мы добавим тег сборки pro и выполним сборку и запуск приложения еще раз:

      Вывод должен выглядеть следующим образом:

      Output

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

      Это все еще не совсем то, что нам нужно: корпоративные функции отображаются при попытке сборки профессиональной версии. Чтобы устранить эту проблему, нам потребуется другой тег сборки. В отличие от тега pro, нам нужно убедиться, что функции профессиональной и корпоративной версий доступны.

      Система сборки Go позволяет решить эту ситуацию посредством использования базовой булевой логики в системе тегов сборки.

      Давайте снова откроем файл enterprise.go​​​:

      Добавьте другой тег сборки, enterprise, в той же строке, что и тег pro:

      enterprise.go

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

      Сохраните и закройте файл.

      Теперь мы скомпилируем и запустим приложение с новым тегом сборки enterprise.

      • go build -tags enterprise
      • ./app

      В результате вы получите следующий вывод:

      Output

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

      Теперь мы потеряли функции профессиональной версии. Это объясняется тем, что при вводе нескольких тегов сборки в одной строке файла .go команда go build интерпретирует их, используя логику OR. После добавления строки //+build pro enterprise файл enterprise.go будет использоваться при сборке, только если любой из тегов сборки pro или enterprise будет присутствовать. Нам нужно корректно настроить теги сборки, чтобы требовать наличие обоих тегов и использовать логику AND.

      Вместо того, чтобы помещать оба тега в одной строке, если мы разместим их в отдельных строках, команда go build будет толковать эти теги, используя логику AND.

      Откройте файл enterprise.go еще раз и поместите теги сборки в разных строках.

      enterprise.go

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

      Теперь мы скомпилируем и запустим приложение с новым тегом сборки enterprise.

      • go build -tags enterprise
      • ./app

      Вывод должен выглядеть следующим образом:

      Output

      > Free Feature #1 > Free Feature #2

      И все равно это еще не все: поскольку оператор AND требует, чтобы оба элемента имели значение true, мы должны использовать оба тега сборки, как pro, так и enterprise.

      Давайте попробуем еще раз:

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

      Вывод должен выглядеть следующим образом:

      Output

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

      Теперь наше приложение можно собирать из одного дерева источника различным образом, разблокируя функции приложения соответствующим образом.

      В данном примере мы использовали новый тег //+build для обозначения логики AND, но есть альтернативные способы использования булевой логики с помощью тегов сборки. В данной таблице приведены примеры других синтаксических форматов для тегов сборки наряду с их эквивалентом в булевой логике:

      Синтаксис тега сборки Пример тега сборки Логический оператор
      Разделенные пробелами элементы // +build pro enterprise pro OR enterprise
      Разделенные запятой элементы // +build pro,enterprise pro AND enterprise
      Элементы с восклицательным знаком // +build ! pro NOT pro

      Заключение

      В этом обучающем руководстве вы использовали теги сборки для контроля того, какая часть кода будет компилироваться в бинарном файле. Сначала вы объявили теги сборки и использовали их с помощью команды go build, а затем сочетали несколько тегов с помощью булевой логики. Затем вы создали программу, представляющую различные наборы функций для бесплатной, профессиональной и корпоративной версий, для демонстрации уровня контроля, который теги сборки могут предоставить для вашего проекта.

      Если вы хотите узнать больше о тегах сборки, посмотрите документацию Golang по этой теме или продолжите изучение нашей серии статей о программировании на языке Go.



      Source link

      Использование тегов структур в Go


      Введение

      Структуры используются для сбора различных элементов информации внутри одной единицы. Эти наборы информации используются для описания концепций более высокого уровня. Так, адрес состоит из области, города, улицы, почтового индекса и т. д. Когда вы считываете эту информацию из баз данных, API или других подобных систем, вы можете использовать теги структур для контроля присвоения этой информации в поля структуры. Структурные теги — это небольшие элементы метаданных, прикрепленные к полям структуры. Они содержат инструкции для другого кода Go, который работает с этой структурой.

      Как выглядит структурный тег?

      Структурные теги в Go представляют собой аннотации, которые отображаются после типа в декларации структуры Go. Каждый тег состоит из коротких строк, которым назначены определенные значения.

      Структурный тег выделяется символами апострофа “”` и выглядит следующим образом:

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

      Другой код Go может оценивать структуры и извлекать значения, назначенные определенным ключам, которые он запрашивает. Структурные теги не влияют на работу кода без кода, который их использует.

      С помощью этого примера вы увидите, как выглядят структурные теги, и как они не действуют без кода из другого пакета.

      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)
      }
      

      Результат будет выглядеть так:

      Output

      Hi! My name is Sammy

      В этом примере определяется тип User с полем Name. Для поля Name назначен структурный тег example:"name". Мы ссылаемся на этот тег как на “структурный тег example”, поскольку в качестве ключа в нем используется слово example. Структурный тег example имеет значение "name" для поля Name. Для типа User мы также определим метод String(), который требуется для интерфейса fmt.Stringer. Он вызывается автоматически при передаче типа в fmt.Println и позволяет нам вывести хорошо отформатированную версию нашей структуры.

      В теле main мы создадим новый экземпляр типа User и передадим его в fmt.Println. Хотя в структуре имеется структурный тег, он не влияет на выполнение этого кода Go. Он выполняется точно так же, как если бы структурного тега не было.

      Чтобы использовать структурные теги для каких-либо целей, необходимо написать другой код Go, который будет запрашивать их во время исполнения. В стандартной библиотеке имеются пакеты, которые используют структурные теги в своей работе. Наиболее популярный из них — пакет encoding/json.

      Кодировка JSON

      JavaScript Object Notation (JSON) представляет собой текстовый формат кодирования наборов данных, организованных по различным ключам строк. Он обычно используется для обмена данными между разными программами, поскольку имеет достаточно простой формат для расшифровки библиотеками многих разных языков. Ниже приведен пример JSON:

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

      Этот объект JSON содержит два ключа, language и mascot. За этими ключами идут связанные с ними значения. Ключ language имеет значение Go, а ключу mascot присвоено значение Gopher.

      Кодировщик JSON в стандартной библиотеке использует структурные теги как аннотацию, указывая кодировщику, какие имена вы хотите присвоить полям в выводимых JSON результатах. Эти механизмы кодировки и декодировки JSON содержатся в пакете encoding/json.

      В этом примере показана кодировка JSON без структурных тегов:

      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))
      }
      

      Этот код распечатывает следующее:

      Output

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

      Мы определили структурный тег, описывающий пользователя с помощью полей, включая имя, пароль и время создания пользователя. В функции main мы создаем экземпляр этого пользователя, предоставляя значения для всех полей, кроме PreferredFish (Sammy нравятся все рыбы). Затем мы передаем экземпляр User в функцию json.MarshalIndent. Это позволяет нам просматривать результаты выполнения JSON в удобном виде без внешнего инструмента форматирования. Этот вызов можно заменить на json.Marshal(u) для получения JSON без дополнительных пробелов. Два дополнительных аргумента json.MarshalIndent определяют префикс результатов (который мы пропустили при выводе пустой строки) и символы отступа, в данном случае — два символа пробела. Любые ошибки json.MarshalIndent регистрируются, и программа завершает работу с помощью os.Exit(1). Наконец, мы кастуем []byte, возвращаемый json.MarshalIndent, в string, а затем передаем эту строку в функцию fmt.Println для печати на терминале.

      Поля структуры соответствуют присвоенным им именам. Это не обычный стиль JSON, где используются названия полей, где первая буква каждого слова, кроме первого, — заглавная («верблюжий стиль»). Вы можете изменить имена полей в соответствии с «верблюжьим стилем», как показано в следующем примере. Как видно при выполнении этого образца, это не сработает, поскольку желаемые имена полей противоречат правилам Go в отношении имен экспортируемых полей.

      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))
      }
      

      В результате выводится следующее:

      Output

      {}

      В этой версии мы изменили имена полей в соответствии с «верблюжьим стилем». Теперь Name соответствует name, Password соответствует password, а CreatedAt соответствует createdAt. В теле main мы изменили инициациализацию структуры для использования новых имен. Затем мы передаем структуру в функцию json.MarshalIndent, как и ранее. Сейчас в результате выводится пустой объект JSON, {}.

      Для правильного отображения полей в «верблюжьем стиле» требуется, чтобы первый символ был в нижнем регистре. Хотя JSON не важны имена полей, для Go они имеют значение, поскольку от этого зависит видимость полей вне пакета. Поскольку пакет encoding/json является отдельным пакетом от используемого нами пакета main, первый символ его имени должен быть в верхнем регистре, чтобы он был видимым для encoding/json. Похоже мы в безвыходном положении, и нам нужен способ передать кодировщику JSON желаемое имя этого поля.

      Использование структурных тегов для управления кодировкой

      Вы можете изменить предыдущий пример так, чтобы экспортируемые поля правильно кодировались с именами полей в «верблюжьем стиле». Для этого мы аннотируем каждое поле структурным тегом. Структурный тег, распознаваемый encoding/json, имеет ключ json и значение, определяющее выводимый результат. Если мы поместим имена полей в «верблюжьем стиле» в качестве значения ключа json, кодировщик будет использовать эти имена. В данном примере решена проблема, наблюдавшаяся в предыдущих двух попытках:

      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))
      }
      

      Результат будет выглядеть так:

      Output

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

      Мы снова изменили имена полей так, чтобы сделать их видимыми для других пакетов. Для этого мы сделали заглавными первые буквы имен этих полей. Однако в этот раз мы добавили структурные теги в форме json:"name", где "name" — имя, которое json.MarshalIndent должен использовать при печати нашей структуры в формате JSON.

      Мы успешно и правильно отформатировали код JSON. Однако следует отметить, что поля для некоторых значений были распечатаны, хотя мы и не задавали эти значения. Если вы захотите, кодировщик JSON может ликвидировать эти поля.

      Удаление пустых полей JSON

      Чаще всего мы не хотим выводить поля, которые не заданы в JSON. Поскольку все типы Go имеют заданное по умолчанию «нулевое значение», пакету encoding/json требуется дополнительная информация, чтобы он считал поле не заданным, если оно имеет это нулевое значение. В части значения любого структурного тега json вы можете задать суффикс желаемого имени поля с опцией ,omitempty, чтобы кодировщик JSON не выводил это поле, если для него задано нулевое значение. В следующем примере мы устранили заметную в предыдущих примерах проблему вывода пустых полей:

      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))
      }
      

      Результат выполнения будет выглядеть так:

      Output

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

      Мы изменили предыдущие примеры так, что теперь поле PreferredFish имеет структурный тег json:"preferredFish,omitempty". Благодаря опции ,omitempty кодировщик JSON пропускает это поле, поскольку мы не задаем его. В предыдущих примерах результатом было значение null.

      Теперь результаты выглядят намного лучше, однако мы по прежнему распечатываем пароль пользователя. Пакет encoding/json дает нам еще один способ полностью игнорировать конфиденциальные поля.

      Игнорирование конфиденциальных полей

      Некоторые поля необходимо экспортировать из структур, чтобы другие пакеты могли правильно взаимодействовать с типом. Однако эти поля могут носить конфиденциальный характер, и в данном случае мы хотим, чтобы кодировщик JSON полностью игнорировал поле—даже если оно задано. Для этого используется специальное значение - в качестве аргумента для структурного тега json:.

      В этом примере мы исправили проблему раскрытия пароля пользователя.

      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))
      }
      

      При запуске этого примера вы увидите следующие результаты:

      Output

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

      Единственное изменение в этом примере по сравнению с предыдущими заключается в том, что в поле пароля теперь используется специальное значение "-" для структурного тега json:. В результатах в этом примере мы видим, что поле password больше не отображается.

      Эти возможности пакета encoding/json, ,omitempty и "-" не являются стандартными. Действия пакета со значениями структурного тега зависят от реализации. Поскольку пакет encoding/json является частью стандартной библиотеки, в других пакетах эти возможности также реализованы стандартным образом. Однако важно ознакомиться с документацией по любым сторонним пакетам, использующим теги структуры, чтобы узнать, что поддерживается, а что нет.

      Заключение

      Структурные теги дают мощные возможности улучшения функциональности кода, работающего с вашими структурами. Многие стандартные библиотеки и сторонние пакеты поддерживают индивидуальные настройки с помощью структурных тегов. Их эффективное использование в коде поддерживает персонализацию поведения, а также в них кратко документируется использование этих полей будущими разработчиками.



      Source link