Показаны сообщения с ярлыком импорт в Go. Показать все сообщения
Показаны сообщения с ярлыком импорт в Go. Показать все сообщения

понедельник, 14 декабря 2020 г.

Go style guides: имена пакетов, импорт

Порядок групп импорта

Следует иметь две группы импорта:

  • Стандартная библиотека
  • Все остальное

Это группировка, применяемая goimports по умолчанию.

Менее удачный вариант:

import (
    "fmt"
    "os"
    "go.uber.org/atomic"
    "golang.org/x/sync/errgroup"
)

Более удачный вариант:

import (
    "fmt"
    "os"

    "go.uber.org/atomic"
    "golang.org/x/sync/errgroup"
)

Имена пакетов

При именовании пакетов выберите такое имя, которое:

  • Все в нижнем регистре. Без заглавных букв и подчеркиваний.
  • Не требует переименования с использованием именованного импорта на большинстве мест вызова.
  • Коротко и емко. Помните, что имя указывается полностью на каждом месте вызова.
  • Не во множественном числе. Например, net/url, а не net/urls.
  • Не "common", "util", "shared", "lib". Это неудачные, малоинформативные имена.

Имена функций

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

Псевдонимы в импорте

Псевдоним импорта необходимо использовать, если имя пакета не соответствует последнему элементу пути импорта.

import (
    "net/http"

    client "example.com/client-go"
    trace "example.com/trace/v2"
)

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

Менее удачный вариант:

import (
    "fmt"
    "os"

    nettrace "golang.net/x/trace"
)

Более удачный вариант:

import (
    "fmt"
    "os"
    "runtime/trace"

    nettrace "golang.net/x/trace"
)


Читайте также:


суббота, 22 июня 2019 г.

Спецификация Go: пакеты

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

Организация исходного файла

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

SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .

Пункт package

Пункт package начинает каждый исходный файл и определяет пакет, к которому принадлежит файл.

PackageClause  = "package" PackageName .
PackageName    = identifier .

PackageName не должно быть пустым идентификатором. Пример:

package math

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

Import объявления

В объявлении импорта указывается, что исходный файл, содержащий объявление, зависит от функциональности импортированного пакета (инициализация и выполнение программы) и обеспечивает доступ к экспортированным идентификаторам этого пакета. При импорте указывается идентификатор (PackageName), который будет использоваться для доступа, и ImportPath, который указывает импортируемый пакет.

ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .

PackageName используется в квалифицированных идентификаторах для доступа к экспортированным идентификаторам пакета в исходном импортирующем файле. Это объявлено в блоке файла. Если PackageName опущено, по умолчанию используется идентификатор, указанный в предложении пакета импортируемого пакета. Если вместо имени появляется явный период (.), все экспортированные идентификаторы пакета, объявленные в блоке пакета этого пакета, будут объявлены в блоке файла импортирующего исходного файла и должны быть доступны без квалификатора.

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

Ограничение реализации: компилятор может ограничивать ImportPaths непустыми строками, используя только символы, принадлежащие общим категориям Unicode L, M, N, P и S (графические символы без пробелов), а также может исключать символы !"#$%&'()*,:;<=>?[\]^`{|} и символ замены Unicode U+FFFD.

Предположим, что мы скомпилировали пакет, содержащий выражение пакета package math, которое экспортирует функцию Sin, и установили скомпилированный пакет в файл, обозначенный как «lib/math». В следующей таблице показано, как обращаться к Sin в файлах, которые импортируют пакет после различных типов объявлений импорта.

Import declaration          локальное имя Sin

import   "lib/math"         math.Sin
import m "lib/math"         m.Sin
import . "lib/math"         Sin

Декларация импорта объявляет отношение зависимости между импортирующим и импортированным пакетом. Запрещается импортировать сам пакет, прямо или косвенно, или напрямую импортировать пакет без ссылки на какие-либо экспортируемые идентификаторы. Чтобы импортировать пакет исключительно для его побочных эффектов (инициализация), используйте пустой идентификатор в качестве явного имени пакета:

import _ "lib/math"

Пример пакета

Вот полный Go пакет, который реализует конкуррентный отсеиватель простых чисел.

package main

import "fmt"

// Отправляем последовательность 2, 3, 4, … в канал 'ch'.
func generate(ch chan<- int) {
  for i := 2; ; i++ {
    ch <- i  // Отправляем 'i' в канал 'ch'.
  }
}

// Копируем значения из канала 'src' в канал 'dst',
// удаляем те что делимы на 'prime'.
func filter(src <-chan int, dst chan<- int, prime int) {
  for i := range src {  // Проходим в цикле по значениям 
                        // полученным из 'src'.
    if i%prime != 0 {
      dst <- i  // Отправляем 'i' в канал 'dst'.
    }
  }
}

// Отсеиватель простых чисел: 
// Гирляндный фильтр работает вместе.
func sieve() {
  ch := make(chan int)  // Создаем новый канал.
  go generate(ch)       // Запускаем generate() 
                        // как подпроцесс.
  for {
    prime := <-ch
    fmt.Print(prime, "\n")
    ch1 := make(chan int)
    go filter(ch, ch1, prime)
    ch = ch1
  }
}

func main() {
  sieve()
}


Читайте также:


суббота, 2 марта 2019 г.

Go Code Review Comments: пустой импорт, импорт точки

Пустой импорт

Пакеты, которые импортируются только для их побочных эффектов (с использованием синтаксиса import _ "pkg"), следует импортировать только в основной пакет программы или в тесты, которые в них нуждаются.

Импорт точки

import . форма может быть полезна в тестах, которые из-за циклических зависимостей не могут быть частью тестируемого пакета:

package foo_test

import (
    "bar/testutil" // также испортирует "foo"
    . "foo"
)

В этом случае тестовый файл не может быть в пакете foo, поскольку он использует bar/testutil, который импортирует foo. Поэтому мы используем import . форму, позволяющую файлу претендовать на то, чтобы быть частью пакета foo, хотя это не так. За исключением этого случая, не используйте import . в ваших программах. Это делает программы намного труднее для чтения, потому что неясно, является ли имя, такое как Quux, идентификатором верхнего уровня в текущем пакете или в импортированном пакете.


Читайте также:


пятница, 1 марта 2019 г.

Go Code Review Comments: импорт

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

Импорт организован в группы с пустыми строками между ними. Пакеты стандартной библиотеки всегда находятся в первой группе.

package main

import (
  "fmt"
  "hash/adler32"
  "os"

  "appengine/foo"
  "appengine/user"

  "github.com/foo/bar"
  "rsc.io/goversion/version"
)

goimports выполняет все эти действия за вас.


Читайте также: