Как отключить неиспользуемую ошибку импорта Golang

99

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

Я нахожу эту проблему очень раздражающей, потому что мне не нравится писать на Go.

Например, я тестировал какой-то код, отключая сегмент / функцию. Некоторые функции из библиотеки больше не используются (например, fmt, errors, что угодно), но мне нужно будет снова включить функцию после небольшого тестирования. Теперь программа не будет компилироваться, если я не удалю этот импорт, а через несколько минут мне нужно повторно импортировать библиотеку.

Я повторял этот процесс снова и снова при разработке программы GAE.

Ник
источник
1
Не рекомендуется оставлять неиспользуемые импорты в коде, но вы можете просто временно закомментировать их.
elithrar
74
Я согласен, что оставлять неиспользуемые импортированные файлы - не лучшая идея, но плохая идея - напрасно тратить усилия программиста на подобные вещи, особенно это происходит очень часто при тестировании чего-либо. Это голосование должно быть связано с моим отношением к ГО со стороны этих фанатов го.
Ник,
6
Это особенность, а не ошибка .
beatgammit
1
Удаление неиспользованного импорта - это хорошо. Существует множество руководств по стилю, которые требуют, чтобы все предупреждения рассматривались как ошибки, поэтому добавление нового предупреждения, как правило, является плохой идеей. Возможно, флаг -dev может быть возможным компромиссом, но он var _ = <module>.Functionработает нормально и достаточно бросается в глаза, чтобы предотвратить его распространение.
deft_code
1
Поскольку кто-то затрагивает ответы ниже, я рекомендую либо использовать среду IDE, которая управляет импортом (Gogland, LiteIDE и т. Д. - их несколько), либо использовать goimportsв качестве шага в процессе сборки. Без любого из них он очень быстро стареет.
Йозеф Гран

Ответы:

40

Добавление символа подчеркивания ( _) перед именем пакета игнорирует неиспользуемую ошибку импорта.

Вот пример того, как вы могли бы это использовать:

import (
    "log"
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

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

См. Больше на https://golang.org/ref/spec#Import_declarations

Кислый9
источник
Это правильный ответ. В соответствии со спецификацией GoLang Doc он предназначен для импорта пакета исключительно для побочных эффектов (инициализации). Документ GoLang Spec здесь: golang.org/ref/spec#Import_declarations
Will
Просто фантастика. Это должно быть в списке из десяти вещей, которые должны знать разработчики, не знакомые с golang. Спасибо!
JM Janzen
13
Не очень полезно. Проблема заключается в том, что если вы позже захотите снова использовать импорт, вы должны удалить _(в противном случае на пакет нельзя будет ссылаться, так как у него нет имени). Если вы собираетесь это сделать, вы можете просто прокомментировать / раскомментировать это. У var _ = ...трюка нет этой проблемы.
EM0
Если вы добавите подчеркивание к "fmt"в Gogland, он автоматически добавится, "fmt"так что у вас есть оба _"fmt"и "fmt", что делает его бесполезным в этой среде IDE
kramer65 08
26

var _ = fmt.PrintfТрюк полезно здесь.

Фолькер
источник
Мне нравится это решение. Это достаточно уродливо, чтобы сделать его нежелательным, но он работает, так что он есть, если вам это действительно нужно.
deft_code
3
Для получения дополнительной информации, пожалуйста, проверьте эту ссылку tip.golang.org/doc/effective_go.html#blank_unused
Дипак Сингх Рават,
3
В данный момент это полезно, но когда я использовал эту технику, я, как правило, не возвращался и не удалял неиспользованный пустой идентификатор позже, в результате чего импорт оставался, когда я действительно не собирался использовать их в долгосрочной перспективе. Использование такого инструмента, как goimports, решило настоящую проблему и гарантирует, что мой импорт всегда минимален и чист.
mdwhatcott
По-прежнему, на мой взгляд, глупый хакер, хотя, вероятно, самый эффективный способ.
Энтони
+1, потому что это можно сделать в любом месте файла , что обычно было бы ужасной идеей, но действительно полезно для избавления вас от необходимости прыгать по файлу, чтобы добраться до importоператора и обратно, когда вы просто пытаетесь скомпилировать или протестировать какой-нибудь файл кода, который вы итеративно дополняете.
mtraceur
22

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

Если вам интересно, вы можете увидеть это на https://github.com/dtnewman/modified_golang_compiler .

Теперь я могу просто запустить код с помощью такой команды, как go run -gcflags '-unused_pkgs' test.go, и она не выдаст эти ошибки «неиспользованного импорта». Если я опущу эти флаги, он вернется к значению по умолчанию, запрещающему неиспользуемый импорт.

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

dtzvi
источник
2
Я также проделал то же самое с выпуском 1.6, если интересно, проверьте здесь: github.com/ronelliott/go/tree/release-branch.go1.6 ПРИМЕЧАНИЕ: некоторые тесты не пройдут
Ron E
2
Мне нравится идея, стоящая за этим. Я вижу, что у вас форк все еще версии 1.2, что делает его бесполезным. Это должно быть включено в стандартный компилятор go, по крайней мере, чтобы go run main.goотключить ошибки по умолчанию, но go buildразрешить ошибки. Таким образом, легко разрабатывать с использованием, go runи когда пришло время создавать для производства, вы все равно вынуждены очищать свой код.
kramer65 08
17

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

mdwhatcott
источник
5

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

Старый
источник
5
Или встроенная функция, о printlnкоторой люди, кажется, всегда забывают.
MatrixFrog
2
@MatrixFrog В конечном счете, не рекомендуется использовать эти функции, поскольку со временем они могут исчезнуть. Использование журнала - хорошая идея, поскольку вы можете сохранить его, и он является частью стандартной библиотеки и вряд ли будет удален. Подробности смотрите в спецификации .
nemo
1
Встроенный println?? Это для меня новость. Это недокументировано? Нигде не могу найти.
Мэтт
1
@nemo хорошее замечание. Они идеально подходят для тех случаев, когда вам нужно что-то быстро распечатать, но вы не собираетесь регистрировать это на самом деле. В любом другом случае, вероятно, не стоит использовать их.
MatrixFrog
1
@MartinTournoij - я не согласен. Это было решение, которое я в конце концов нашел, когда у меня возникла эта проблема 5 лет назад, и с 5+ голосами за него оно явно помогло другим. Я был новичком, использующим fmtпакет для ведения журнала, не подозревая, что существует готовый пакет для ведения журнала.
OldCurmudgeon
5

Используйте, if false { ... }чтобы закомментировать код. Код внутри фигурных скобок должен быть синтаксически правильным, но в противном случае может быть бессмысленным кодом.

топскип
источник
3
Более чем синтаксически правильные, любые ссылочные переменные (например, foo.Bar) должны существовать и т. Д.
Dragon
Это не очень чисто или идиоматично. Есть причина, по которой Go был разработан таким, каким он был
Acidic9
1
Это хороший метод, когда вы просто пробуете что-то при разработке сценария или изучении API в Golang. Спасибо, топскип!
Джей Тейлор
2

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

Короче говоря, неиспользуемый импорт считается ошибкой в ​​Go, поскольку он загрязняет программу и замедляет компиляцию. Использование импорта для побочного эффекта (_) - это обходной путь, однако я нахожу это иногда сбивающим с толку, когда есть сочетание действительного импорта с побочными эффектами вместе с побочными эффектами, импортированными исключительно с целью отладки / тестирования, особенно когда база кода большой, и есть шанс забыть и не удалить случайно, что может запутать других инженеров / рецензентов позже. Раньше я закомментировал неиспользуемые, однако популярные IDE, такие как VS code и Goland, можно goimportsлегко использовать, что делает вставку и удаление импорта довольно хорошо. Для получения дополнительной информации перейдите по ссылке https://golang.org/doc/effective_go.html#blank_import.

sbcharr
источник
Спасибо за это! Я бы предложил явно скопировать строку кода из URL-адреса, который вы разместили в своем ответе, в качестве конкретного примера импорта для побочного эффекта: import _ "net/http/pprof"
Dragon
1
Спасибо @Dragon за ваше предложение! Поскольку я новый участник, с помощью таких людей, как вы, я быстро поправлюсь в своих сообщениях.
sbcharr
-1

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

import (
    "bufio"
    "fmt"
    "os"
    "path/filepath"
)

var _, _, _, _ = fmt.Println, bufio.NewReader, os.Open, filepath.IsAbs
Goen
источник
1
Вместо того, чтобы заставлять компилятор генерировать мертвый код, если вы действительно хотели это сделать, используйте _вместо этого глобальные переменные (например, один пакет на строку или, если вы настаиваете, все вместе, например:) var _, _, _, _ = fmt.Println, bufio.NewReader, os.Open, filepath.IsAbs. Но не делайте этого, просто используйте goimports.
Dave C