Что это '.' (точка или точка) в операторе импорта Go?

135

В руководстве по Go и большей части кода Go, на который я смотрел, пакеты импортируются следующим образом:

import (
    "fmt"
    "os"
    "launchpad.net/lpad"
    ...
)

Но в http://bazaar.launchpad.net/~niemeyer/lpad/trunk/view/head:/session_test.go пакет gocheck импортируется с .(точка):

import (
    "http"
    . "launchpad.net/gocheck"
    "launchpad.net/lpad"
    "os"    
)

Какое значение имеет .(период)?

Эрик Зайдель
источник
22
Обратите внимание, я добавил точку и точку к вопросу, чтобы упростить поиск.
Джаред Фарриш

Ответы:

182

Это позволяет ссылаться на идентификаторы в импортированном пакете в локальном файловом блоке без квалификатора.

Если вместо имени появляется явный период (.), Все экспортированные идентификаторы пакета будут объявлены в блоке файла текущего файла и доступны без спецификатора.

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

Import declaration          Local name of Sin

import   "lib/math"         math.Sin
import M "lib/math"         M.Sin
import . "lib/math"         Sin

Ссылка: http://golang.org/doc/go_spec.html#Import_declarations

tvanfosson
источник
29
Следует отметить, что команда Go не рекомендует использовать точечный импорт. В некоторых случаях это может привести к некоторому странному поведению и может отсутствовать в языке бесконечно долго.
Джимт
Это может сбивать с толку в некоторых сценариях, но я не выдержал использования go-linq. github.com/ahmetalpbalkan/go-linq
steviesama
Обратите внимание, что вы все еще не можете получить доступ к неэкспортированным функциям (не прописным функциям). Так что этот способ импорта действительно отстой.
Дэвид 天宇 Вонг
1
При компиляции программы с использованием точечного импорта и без точечного импорта. Есть ли причина, почему существует огромная разница, если размер скомпилированного файла? Использование точечного импорта компилирует в больший размер.
Маджидариф
@majidarif: Это интересное наблюдение :) Не могли бы вы опубликовать отдельный вопрос для этого с кодом, который воспроизводит проблему? (Я попытался сделать это сам, скомпилировав простую программу hello-world с import "fmt"vs import . "fmt", но в обоих случаях это был один и тот же размер для меня.)
Attilio
66

Вот аналогия для тех, кто приходит с Python:

  • Go's import "os"примерно эквивалентно Pythonimport os
  • Go's import . "os"примерно эквивалентно Pythonfrom os import *

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

Эван Шоу
источник
4

Это следует использовать только в тестировании.

Вот некоторая документация в вики Голанга

Если вы сгенерировали какой-то фиктивный код, например, с помощью mockgen, и он импортирует код вашего пакета, а затем ваш тестовый пакет также импортирует код вашего пакета, вы получаете циклическую зависимость (что-то, что golang выбирает, чтобы пользователь мог решить, как решить).

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

Эли Дэвис
источник