目次
Go Module" >Go Module
创建 Go module" >创建 Go module
创建一个自定义包:计算利息" >创建一个自定义包:计算利息
导入自定义包" >导入自定义包
关于 go install 更多的知识" >关于 go install 更多的知识
可导出" >可导出
init 函数" >init 函数
空白符 _" >空白符 _
ホームページ バックエンド開発 Golang Go 言語の基本パッケージ

Go 言語の基本パッケージ

Jul 21, 2023 am 11:56 AM
言語を移動

パッケージとは何ですか?なぜそれを使用するのでしょうか?

これまで見てきた Go プログラムにはファイルが 1 つだけあり、そのファイルには main 関数とその他のいくつかの関数が含まれています。実際のビジネス開発では、すべてのソース コードを 1 つのファイルに記述するこの方法は拡張性がありません。この種のコードの再利用性と保守性は不可能になるため、ここでパッケージが役に立ちます。

パッケージは、同じディレクトリにある .go で終わるファイルのコレクションであり、再利用性と読みやすさを向上させるためにソース コードを整理するために使用されます。パッケージは、Go プロジェクトの保守を容易にするコード分割を提供します。

たとえば、単利計算、複利計算などの関数を含む金融システムを Go で作成しているとします。このシステムを編成する簡単な方法は、機能に応じて分割することです。単純金利、複利、ローンの 3 つのパッケージを作成できます。ローン パッケージで simpleinterest パッケージの機能を使用する必要がある場合は、simpleinterest パッケージをインポートするだけで済み、コードを再利用できます。

元本、利率、および時間を与えてどれだけの利息が得られるかを計算する簡単なアプリケーションを作成することで、このパッケージについて学習します。

main 関数とメイン パッケージ

すべての実行可能な Go アプリケーションには main 関数が含まれている必要があります。この関数はプログラム実行のエントリ ポイントであり、main 関数はメイン パッケージに含まれている必要があります。

package packagename
ログイン後にコピー

上記の構文は、ソース ファイルが packagename パッケージに属することを指定するために使用され、通常はファイルの最初の行に表示されます。

アプリケーションの main 関数と main パッケージの作成を始めましょう。

次のコマンドを実行して、現在のユーザーのドキュメント ディレクトリに learnpackage という名前のディレクトリを作成します。

mkdir ~/Documents/learnpackage/
ログイン後にコピー

learnpackage ディレクトリに main.go という名前のファイルを作成します。このファイルには次のコードが含まれます:

package main

import "fmt"

func main() {
    fmt.Println("Simple interest calculation")
}
ログイン後にコピー

パッケージのメイン コードは、ファイルがメイン パッケージに属することを指定するために使用されます。

#import "packagename" ステートメントは既存のパッケージをインポートするために使用されます;

packagename.FunctionName() はパッケージ内の関数を呼び出すために使用されます;

上面代码的第 3 行,我们导入 fmt 包以便能调用包里的 Println() 函数,fmt 是 Go 语言标准库中内置的一个包。主函数会打印 Simple interest calculation。

cd 到 learnpackage 目录并且编译上面的代码

cd ~/Documents/learnpackage/
go install
ログイン後にコピー

如果一切顺利,二进制文件将被编译并可以执行。在终端中键入命令 learnpackage,将会看到如下输出:

Simple interest calculation
ログイン後にコピー

Go Module

我们将会这样构建代码,与计算利息相关的功能函数都放在 simpleinterest 包里。为此,我们需要创建一个自定义包 simpleinterest,其中包含计算利息的函数。在创建自定义包之前,我们需要先了解 Go Modules,创建自定义包需要 Go Modules。

简单来说,Go Module 只不过是 Go 包的集合。你可能会有疑问,为什么我们需要 Go 模块来创建自定义包呢?答案是我们创建的自定义包的导入路径来源于 go 模块的名称。除此之外,我们的应用程序使用的所有其他第三方包(例如来自 github 的源代码)将与版本一起出现在 go.mod 文件中。当我们创建一个新模块时,会创建出一个 go.mod 文件,下一小节会讲到这点。

可能你又会疑惑了:为什么到现在我们还没有创建 Go 模块程序也能执行成功?答案是,本系列教程到目前为止,我们从未创建过自定义包,因此不需要 Go 模块。

理论知识学完了,让我们来创建自己的 Go 模块和自定义包。

创建 Go module

执行下面命令确保在 learnpackage 目录下,

cd ~/Documents/learnpackage/
ログイン後にコピー

在该目录下输入如下命令创建名为 learnpackage 的 go 模块。

go mod init learnpackage
ログイン後にコピー

上面的命令将创建一个名为 go.mod 的文件,下面是该文件的内容:

module learnpackage

go 1.13
ログイン後にコピー

代码行 module learnpackage 指定模块的名字为 learnpackage。正如之前提到的,learnpackage 是模块的基础路径,想要导入模块的任何一个包必须基于此路径。最后一行指定此模块中的文件使用 1.13 的 go 版本。

创建一个自定义包:计算利息

属于一个包的源文件应该放在它们自己的单独文件夹中。Go 中的约定是文件夹名称与包名相同。

让我们在 learnpackage 文件夹中创建一个名为 simpleinterest 的文件夹。mkdir simpleinterest 将会创建该文件夹。

simpleinterest 文件夹中的所有文件都应该以 package simpleinterest 开头,因为它们都属于 simpleinterest 包。

在 simpleinterest 文件夹中创建一个文件 simpleinterest.go。

下面是程序的结构目录:

├── learnpackage
│   ├── go.mod
│   ├── main.go
│   └── simpleinterest
│       └── simpleinterest.go
ログイン後にコピー

将以下代码添加到 simpleinterest.go 文件中。

package simpleinterest

//Calculate calculates and returns the simple interest for a principal p, rate of interest r for time duration t years
func Calculate(p float64, r float64, t float64) float64 {
    interest := p * (r / 100) * t
    return interest
}
ログイン後にコピー

在上面的代码中,我们创建了一个计算并返回利息的函数 Calculate()。

导入自定义包

要使用自定义包,我们必须先导入它。导入路径是模块名加上包的子目录和包名。在我们的例子中,模块名称是 learnpackage,包 simpleinterest 位于 learnpackage 下的 simpleinterest 文件夹中。

├── learnpackage
│   └── simpleinterest
ログイン後にコピー

所以 import "learnpackage/simpleinterest" 代码将导入 simpleinterest 包。

如果我们的目录结构是这样的:

learnpackage
│   └── finance
│       └── simpleinterest
ログイン後にコピー

那么导入包的语句将会是 mport "learnpackage/finance/simpleinterest"。

将下面的代码加入 main.go

package main

import (
    "fmt"
    "learnpackage/simpleinterest"
)

func main() {
    fmt.Println("Simple interest calculation")
    p := 5000.0
    r := 10.0
    t := 1.0
    si := simpleinterest.Calculate(p, r, t)
    fmt.Println("Simple interest is", si)
}
ログイン後にコピー

上面的代码导入了 simpleinterest 包并使用了 Calculate() 函数来计算利息。标准库中的包不需要模块名称前缀,比如直接导入 fmt 包也是可以的。执行代码输出:

Simple interest calculation
Simple interest is 500
ログイン後にコピー

关于 go install 更多的知识

现在我们了解了包的工作原理,是时候来讨论关于 go install 的用法了。像 go install 这样的 Go 工具在当前目录的上下文中工作。我们来理解是什么意思,到目前为止,我们一直在目录 ~/Documents/learnpackage/ 中运行 go install。如果我们尝试在其他任何目录执行这个命令,将会报错。

尝试执行命令 cd ~/Documents/ 然后运行 go install learnpackage,它将失败并出现以下错误:

can't load package: package learnpackage: cannot find package "learnpackage" in any of:
    /usr/local/Cellar/go/1.13.7/libexec/src/learnpackage (from $GOROOT)
    /Users/nramanathan/go/src/learnpackage (from $GOPATH)
ログイン後にコピー

我们一起来分析下错误的原因,go install 需要一个可选的包名作为参数(在我们的例子中包名是 learnpackage),如果执行命令的当前目录或者其父级目录下存在这个包,它会尝试编译 main 函数。

我们在 Documents 目录中没有 go.mod 文件,因此 go install 会提示找不到包 learnpackage。

当我们 cd 到 ~/Documents/learnpackage/ 目录时,该目录下存在 go.mod 文件,该文件中指定了模块名称 learnpackage。

所以 go install learnpackage 将在 ~/Documents/learnpackage/ 目录中工作。

但是到目前为止,我们只是在使用 go install 并且没有指定包名。如果没有指定包名,go install 将默认为当前工作目录中的模块名,这就是我们没有指定包名但仍然能执行成功的原因。因此,在 ~/Documents/learnpackage/ 目录下执行下面 3 个命令是等效的:

go install

go install .

go install learnpackage
ログイン後にコピー

上面我们提到 go install 能够递归地在父目录中搜索 go.mod 文件,让我们检查一下这点是否正确。

cd ~/Documents/learnpackage/simpleinterest/
ログイン後にコピー

执行上面的命令 cd 到 simpleinterest 目录,在该目录下执行下面的命令:

go install learnpackage
ログイン後にコピー

Go install 将能在父目录 learnpackage 中找到一个 go.mod 文件,该文件定义了模块 learnpackage,因此它可以工作。

可导出

simpleinterest 包里的 Calculate() 函数开头字母是大写的。这在 Go 中有特别的定义,任何以大写字母开头的变量或函数都是可导出。只能访问其他包中可导出的变量或者函数,在我们这个例子中,我们能在 main 包里访问 Calculate() 函数,因为它是可导出的。

如果将 Calculate() 函数开头字母小写 calculate(),再次尝试从 main 包访问,将会报错:

# learnpackage
./main.go:13:8: cannot refer to unexported name simpleinterest.calculate
./main.go:13:8: undefined: simpleinterest.calculate
ログイン後にコピー

因此,如果你想从其他包能访问包内的函数,则应将其首字母大写。

init 函数

Go 里每个包都可以包含一个 init() 函数。init() 函数不能有任何返回值,也不能有任何参数。在代码中不能显式地调用 init() 函数,包初始化时会自动调用 init() 函数。init() 函数语法如下:

func init() {
}
ログイン後にコピー

init() 函数可以用于执行初始化任务,也可用于程序运行前一些参数的验证。

包的初始化顺序如下:

1.首先初始化包级别的变量;2.接着会调用 init() 函数,一个包可以有多个 init() 函数(在单个文件中或分布在多个文件中),它们按照呈现给编译器的顺序被调用;

如果一个包导入其他包,则首先初始化导入的包。

一个包即使被多个包导入,也只会被初始化一次。

我们对之前的程序做一些修改,以便能更好地学习了解 init() 函数。

首先,让我们将 init 函数添加到 simpleinterest.go 文件中。

package simpleinterest

import "fmt"

/*
 * init function added
 */
func init() {
    fmt.Println("Simple interest package initialized")
}
//Calculate calculates and returns the simple interest for principal p, rate of interest r for time duration t years
func Calculate(p float64, r float64, t float64) float64 {
    interest := p * (r / 100) * t
    return interest
}
ログイン後にコピー

上面的代码添加了一个简单的 init 函数,它只负责打印 Simple interest package initialized。

现在,我们来修改下 main 包,我们都知道计算利息时、利率和时间都应该大于零,我们将在 main.go 文件里定义包级别的变量并且在 init() 函数校验这些变量。

main.go 文件如下:

package main

import (
    "fmt"
    "learnpackage/simpleinterest" //importing custom package
    "log"
)
var p, r, t = 5000.0, 10.0, 1.0

/*
* init function to check if p, r and t are greater than zero
 */
func init() {
    println("Main package initialized")
    if p < 0 {
        log.Fatal("Principal is less than zero")
    }
    if r < 0 {
        log.Fatal("Rate of interest is less than zero")
    }
    if t < 0 {
        log.Fatal("Duration is less than zero")
    }
}

func main() {
    fmt.Println("Simple interest calculation")
    si := simpleinterest.Calculate(p, r, t)
    fmt.Println("Simple interest is", si)
}
ログイン後にコピー

main.go 修改如下:

1.p、r 和 t 变量从主函数级别移至包级别。2.添加了一个 init() 函数,如果本 金、利率或时间有一个小于 0,log.Fatal() 会打印日志并终止程序。

初始化顺序如下:

1.导入的包首先被初始化,因此 simpleinterest 包首先被初始化并且它的 init 方法被调用。2.接下来初始化包级变量 p、r 和 t。3.接着调用 main.go 里的 init() 函数。4.最后调用 main() 函数。

执行程序将会输出:

Simple interest package initialized
Main package initialized
Simple interest calculation
Simple interest is 500
ログイン後にコピー

正如我们预期的那样,simpleinterest 包的 init 函数首先被调用,然后是包级变量 p、r 和 t 的初始化,接下来调用 main 包的 init() 函数,它检查 p、r 和 t 是否小于零,如果 if 语句为真则会终止程序。关于 if 语句的使用我们将在另外章节介绍。在我们的程序里,所有的 if 条件都为 false,程序继续执行,最后调用 main() 函数。

我们来简单修改下代码,

将 main.go 文件的这行代码:

var p, r, t = 5000.0, 10.0, 1.0
ログイン後にコピー

修改成:

var p, r, t = -5000.0, 10.0, 1.0
ログイン後にコピー

我们已将 p 初始化为负数。

现在如果执行程序就会输出:

Simple interest package initialized
Main package initialized
2020/02/15 21:25:12 Principal is less than zero
ログイン後にコピー

因为 p 是负数,所有程序在输出 Principal is less than zero 之后便终止了。

空白符 _

源代码里导入包如果不适用是非法的,编译器编译时会提示,这样做的原因是为了避免未使用的包太多,这将显着增加编译时间。将 main.go 中的代码替换为以下内容:

package main

import (
        "learnpackage/simpleinterest"
)

func main() {

}
ログイン後にコピー

执行上面的代码将会报错:

# learnpackage
./main.go:4:2: imported and not used: "learnpackage/simpleinterest"
ログイン後にコピー

但是在平时开发时,导入一个包可能现在不用,在之后代码的某个地方使用是很常见的,这时候该怎么办?

这时候空白符 _ 就能派上用场了,上面代码的报错可以使用空白符消除。

package main

import (
        "learnpackage/simpleinterest"
)

var _ = simpleinterest.Calculate

func main() {

}
ログイン後にコピー

上面的代码行 var _ = simpleinterest.Calculate 虽然能消除错误,但是不建议这种方式,我们应该特别留意这类代码,并在程序开发完成之后删除,包括导入但未使用的包。因此,建议在使用 import 导入包时使用 _ 消除此类错误。

有时我们导入一个包只是为了确保初始化,即使我们不需要使用包中的任何函数或变量。例如,我们可能需要确保调用 simpleinterest 包的 init 函数,即使我们不需要用到包里的任何函数或者变量。这种情况下也可以使用 _ 空白标识符,如下所示:

package main

import (
    _ "learnpackage/simpleinterest"
)

func main() {

}
ログイン後にコピー

执行上面的代码会输出 Simple Interest package initialized,我们已经成功地初始化了 simpleinterest 包,即使它没有在代码中的任何地方被使用。

以上がGo 言語の基本パッケージの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

モバイルIoT開発におけるGolangテクノロジーの役割 モバイルIoT開発におけるGolangテクノロジーの役割 May 09, 2024 pm 03:51 PM

Go 言語は、高い同時実行性、効率性、クロスプラットフォームの性質により、モバイル モノのインターネット (IoT) アプリケーション開発にとって理想的な選択肢となっています。 Go の同時実行モデルは、ゴルーチン (軽量コルーチン) を通じて高度な同時実行性を実現しており、同時に接続された多数の IoT デバイスを処理するのに適しています。 Go はリソース消費が少ないため、コンピューティングとストレージが限られているモバイル デバイス上でアプリケーションを効率的に実行できます。さらに、Go のクロスプラットフォーム サポートにより、IoT アプリケーションをさまざまなモバイル デバイスに簡単に展開できます。実際のケースでは、Go を使用して BLE 温度センサー アプリケーションを構築し、BLE を介してセンサーと通信し、受信データを処理して温度測定値を読み取り、表示する方法を示します。

golang フレームワークの利点は何ですか? golang フレームワークの利点は何ですか? Jun 06, 2024 am 10:26 AM

Golang フレームワークの利点 Golang は、マイクロサービスや分散システムに特に適した高性能の同時プログラミング言語です。 Golang フレームワークは、既製のコンポーネントとツールのセットを提供することで、これらのアプリケーションの開発を容易にします。 Golang フレームワークの主な利点の一部を次に示します。 1. 高いパフォーマンスと同時実行性: Golang 自体は、その高いパフォーマンスと同時実行性で知られています。コードの同時実行を可能にする軽量のスレッド メカニズムであるゴルーチンを使用することで、アプリケーションのスループットと応答性が向上します。 2. モジュール性と再利用性: Golang フレームワークは、モジュール性と再利用可能なコードを奨励します。アプリケーションを独立したモジュールに分割することで、コードを簡単に保守および更新できます。

ブロックチェーン IoT シナリオにおける Golang 言語の応用の探求 ブロックチェーン IoT シナリオにおける Golang 言語の応用の探求 May 09, 2024 pm 02:48 PM

Go 言語はブロックチェーン IoT シナリオで広く使用されており、その主な利点には、スマート コントラクトの作成、ブロックチェーン上の商品フローのルールと操作の管理が含まれます。資産取引を管理し、資産の場所とステータスを追跡するアプリケーションを開発します。効率的で同時実行のオープンソースで、大量のデータの処理に適しており、拡張やカスタマイズが簡単です。

Go ではパッケージの依存関係はどのように機能しますか? Go ではパッケージの依存関係はどのように機能しますか? Jun 01, 2024 pm 10:40 PM

Go 言語では、パッケージの依存関係は import ステートメントを通じて管理されます。 Go 言語のパッケージ依存関係には、直接依存関係と間接依存関係の 2 種類があります。 Go モジュール システムは、モジュール化、依存関係のバージョン管理、依存関係のダウンロードとインストールなどのタスクを含む、gomod ツールを通じてパッケージの依存関係を管理します。

Go 言語でパイプラインを使用してプロデューサー/コンシューマー パターンを実装するにはどうすればよいですか? Go 言語でパイプラインを使用してプロデューサー/コンシューマー パターンを実装するにはどうすればよいですか? Jun 02, 2024 pm 03:28 PM

プロデューサー/コンシューマー モデルでは、プロデューサーがデータをキャッシュに入れると同時に、コンシューマーは処理のためにそこからデータを抽出できます。 Go では、パイプは次のパターンを実装する通信メカニズムです。パイプを作成します: make(chanT)。ここで、T は転送データ型です。プロデューサー関数: データをパイプ (ch

Go 言語でパイプラインを使用して並列タスクを作成するにはどうすればよいですか? Go 言語でパイプラインを使用して並列タスクを作成するにはどうすればよいですか? Jun 04, 2024 pm 02:46 PM

パイプは、並列タスクの作成に使用できるバッファーなしの通信メカニズムです。 パイプの作成: ch:=make(chanint) データの送信: ch

Go言語でパイプを使用してデータを渡すにはどうすればよいですか? Go言語でパイプを使用してデータを渡すにはどうすればよいですか? Jun 01, 2024 pm 04:15 PM

Go 言語パイプラインはゴルーチン間でデータを転送するために使用され、次の手順で使用できます: パイプラインの作成: make(chanint) データの送信: channel&lt;-data データの受信: data:=&lt;-channel バッファー パイプの作成: make(chanint,10 ) (バッファサイズは 10) 実際のケース: 整数の 2 乗の合計を同時に計算し、パイプを使用して結果をゴルーチンに転送します。

Go言語とブロックチェーン技術の融合と今後の発展展望 Go言語とブロックチェーン技術の融合と今後の発展展望 May 09, 2024 pm 01:09 PM

Go 言語は、その高いパフォーマンス、スケーラビリティ、使いやすさにより、ブロックチェーン開発の最初の選択肢となっています。これは、主要な Hyperledger Fabric コンポーネント (チェーンコード、コンセンサス メカニズム) を実装するために使用され、将来的には分散型アプリケーション、IoT、および相互運用性ソリューションの開発を推進します。

See all articles