乐趣区

关于golang:了解Go中如何使用包变量和函数

简介

在上一个模块中,你配置了一个 Go 环境,用于创立和运行 Go 中所编写的程序。此外,你还理解到 Go 程序的编码构造基本知识,以及如何编译和运行应用程序。

在此模块中,你将逐渐学习中 Go 提供的根本数据类型,并应用函数组织在 .go 文件中编写的代码。你还将理解如何在同一包下的不同文件中治理和编写程序。最初,你将理解如何在 Go 中创立和应用包。

学习指标

在此模块中,你将:

  • 申明变量和常量
  • 理解 Go 提供的根本数据类型
  • 编写函数
  • 创立和应用包

先决条件

  • 可供创立应用程序的 Go 环境
  • 可能创立和批改 .go 文件
  • 可能应用终端运行 Go 应用程序

申明和应用变量

申明变量

若要申明变量,须要应用 var 关键字:

`var firstName string` 

前一个语句申明 string 类型中的一个名为firstName 的变量。(咱们将在后续章节中探讨数据类型。)此示例演示申明变量的最根本办法。如要申明其余变量,只需将相似的语句增加到上一个语句中。但如果两个变量的类型雷同,则能够在一行中申明多个变量:

`var firstName, lastName string` 

通过在变量名称前面增加逗号 (,),就示意你将要申明其余变量。在这种状况下,前一个语句就申明了 string 类型中的两个变量:firstNamelastName。如要增加 int 类型的第三个变量,请按如下所示编写代码:

`var firstName, lastName string
var age int` 

另一种编写前一个语句的办法是在 var 关键字前面应用括号,就像通过一个专用块来申明变量一样,如下所示:

`var (
    firstName, lastName string
    age int
)` 

初始化变量

此时,你只可申明了变量,但有时候,你须要为它们赋予初始值。在 Go 中,你能够通过多种形式初始化变量。例如,沿用后面提及的同一个示例,你能够应用此代码初始化每个变量:

`var (
    firstName string = "John"
    lastName  string = "Doe"
    age       int    = 32
)` 

如果你决定初始化某个变量,则不须要指定其类型,因为当你应用具体值初始化该变量时,Go 会推断出其类型。例如,你能够用此形式申明并初始化变量:

`var (
    firstName = "John"
    lastName  = "Doe"
    age       = 32
)` 

Go 将推断出变量 firstNamelastName 的类型为 string,并且变量 age 属于 int 类型。

通过多种形式初始化变量

在 Go 中,你能够在单行中申明和初始化变量。应用逗号将每个变量名称隔开,并对每个值执行雷同的操作(按同一程序),如下所示:

`var (firstName, lastName, age = "John", "Doe", 32)` 

还能够通过另一种形式来申明和初始化变量。此办法是在 Go 中执行此操作的最常见办法。以下是咱们应用的同一个示例阐明:

`func main() {
    firstName, lastName := "John", "Doe"
    age := 32
    println(firstName, lastName, age)
}` 

运行上述代码,确认此办法是否申明和初始化变量。

请留神,在定义变量名称后,须要在此处退出一个冒号等于号 (:=) 和相应的值。应用冒号等于号时,要申明的变量必须是新变量。如果应用冒号等于号并曾经申明该变量,将不会对程序进行编译。持续尝试。

最终,你能在函数内应用冒号等于号。在申明函数外的变量时,必须应用 var 关键字执行此操作。如果你不相熟函数,请不要放心。咱们会在后续单元中介绍函数。

申明常量

有时,你须要在代码中退出动态值,这称为 常量。Go 反对应用常量。用于申明常量的关键字是 const

例如,你能够按如下所示申明常量:

`const HTTPStatusOK = 200` 

与变量一样,Go 能够通过调配给常量的值推断出类型。在 Go 中,常量名称通常以混合大小写字母或全副大写字母书写。

如果须要在一个块中申明多个常量,能够按如下所示执行:

`const (
    StatusOK              = 0
    StatusConnectionReset = 1
    StatusOtherError      = 2
)` 

备注: Go 为常量定义了一个乏味的概念,即 iota,本模块未对此概念作进一步解释。但你能够查看 GitHub 上的 Go wiki 理解更多信息。请记住,iota 是一个关键字;如果这些值存在先后顺序,Go 可应用此关键字简化常量定义。

常量和变量之间既有相似之处,也有一些重要差别。例如,你能够在不应用常量的状况下申明常量。你不会收到谬误音讯。不能应用冒号等于号来申明常量。如果采纳这种形式,Go 会收回正告。

如果申明了变量但未应用,Go 会抛出谬误

须要记住的重要一点是,在 Go 中,当你申明一个变量但不应用它时,Go 会抛出谬误,而不是像某些其余编程语言一样抛出正告。

例如,让咱们回到后面提及的某个示例,而后删除 println 调用:

`func main() {
    firstName, lastName := "John", "Doe"
    age := 32
}` 

你将看到以下谬误音讯:

`./main.go:4:2: firstName declared but not used
./main.go:4:13: lastName declared but not used
./main.go:5:2: age declared but not used` 

请记住,对于在 Go 中申明的每个变量,你必须将其用于某处。

理解根本数据类型

Go 是一种强类型语言。这意味着你申明的每个变量都绑定到特定的数据类型,并且只承受与此类型匹配的值。

Go 有四类数据类型:

  • 根本类型:数字、字符串和布尔值
  • 聚合类型:数组和构造
  • 援用类型:指针、切片、映射、函数和通道
  • 接口类型:接口

在此模块中,咱们仅介绍根本类型。如果你不晓得其余类型是什么,请不要放心。咱们将在后续模块中进行介绍。

首先,咱们一起浏览数值的数据类型。

整数数字

一般来说,定义整数类型的关键字是 int。但 Go 还提供了 int8int16int32int64 类型,其大小别离为 8163264 位的整数。当你只应用 int 时,32 位零碎上的大小为 32 位,64 位零碎上则为 64 位(大多数状况下如此,不过在不同计算机上或有所不同)。如果须要将值示意为无符号数字,则能够应用 uint,但仅当有特定起因时才应用此类型。此外,Go 还提供 uint8uint16uint32uint64 类型。

上面的示例演示如何在 Go 中应用各种整数类型:

`var integer8 int8 = 127
var integer16 int16 = 32767
var integer32 int32 = 2147483647
var integer64 int64 = 9223372036854775807
println(integer8, integer16, integer32, integer64)` 

大多数状况下,你将应用 int,但须要理解其余整数类型,因为在 Go 中,intint32 不同,即便整数的天然大小为 32 位也是如此。换句话说,须要强制转换时,你须要进行显式转换。如果尝试在不同类型之间执行数学运算,将会呈现谬误。例如,假设你具备上面的代码:

`var integer16 int16 = 127
var integer32 int32 = 32767
println(integer16 + integer32)` 

运行该程序时,你会收到以下谬误:

`invalid operation: integer16 + integer32 (mismatched types int16 and int32)` 

正如你所见,不同于其余编程语言,在 Go 中将值从一种类型转换为另一种类型时,你须要执行显式操作。咱们将在本模块完结时探讨如何正确地强制转换类型。

在学习 Go 过程中,你可能会收到无关 runes 的信息。rune 只是 int32 数据类型的别名。它用于示意 Unicode 字符(或 Unicode 码位)。例如,假如你具备以下代码:

`rune := 'G'
println(rune)` 

运行后面的代码片段时,你可能会在命令提示符下看到程序打印符 G。不过,你还会看到数字 71,它示意 GUnicode 字符。咱们将在后续模块中具体介绍 runes。

你能够通过查看 Go 源代码来理解每种类型的范畴。理解每种类型的范畴可帮忙你抉择正确的数据类型,并且还可防止占用内存中的位。

挑战 1:
设置 int 类型的另一个变量,并应用 integer32integer64 变量中的值来确认零碎上变量的天然大小。如果你应用的是 32 位零碎并应用大于 2,147,483,647 的值,则会呈现如下的溢出谬误:constant 9223372036854775807 overflows int。

质询解决方案:

`package main

func main() {
   var integer32 int = 2147483648
   println(integer32)
}` 

挑战 2:
申明一个无符号变量(如 uint),并用一个负值(如 -10)对其进行初始化。尝试运行程序时,应会呈现如下谬误:constant -10 overflows uint。

质询解决方案:

`package main

func main() {
   var integer uint = -10
   println(integer)
}` 

浮点数字

Go 提供两种浮点数大小的数据类型:float32float64。如果须要存储较大的数字,则能够应用这些类型,这些类型无奈适应后面提到的任何一个整数类型。这两种类型的区别是它们能够包容的最大位数。查看以下行,理解如何应用这两种类型:

`var float32 float32 = 2147483647
var float64 float64 = 9223372036854775807
println(float32, float64)` 

你能够应用 math 包中提供的 math.MaxFloat32math.MaxFloat64 常量来查找这两种类型的限度。应用以下代码打印命令提示符中的最大浮点值:

`package main

import "math"

func main() {println(math.MaxFloat32, math.MaxFloat64)
}` 

当须要应用十进制数时,浮点类型也很有用。例如,你能够编写相似于以下代码的内容:

`const e = 2.71828
const Avogadro = 6.02214129e23
const Planck = 6.62606957e-34` 

请留神,与后面的代码一样,Go 会从应用的值推断其数据类型。

布尔型

布尔类型仅可能有两个值:truefalse。你能够应用关键字 bool 申明布尔类型。Go 不同于其余编程语言,在 Go 中,你不能将布尔类型隐式转换为 01。你必须显式执行此操作。

因而,你能够按如下形式申明布尔变量:

`var featureFlag bool = true` 

当咱们探讨 Go 中的控制流语句时,咱们将在后续模块中应用布尔数据类型。咱们还将在当前的模块中应用这些类型。

字符串

最初,让咱们看一下编程语言中最常见的数据类型:string。在 Go 中,关键字 string 用于示意字符串数据类型。若要初始化字符串变量,你须要在双引号 (") 中定义值。单引号 (') 用于单个字符(以及 runes,正如咱们在上一节所述)。

例如,上面的代码演示了申明和初始化字符串变量的两种办法:

`var firstName string = "John"
lastName := "Doe"
println(firstName, lastName)` 

有时,你须要对字符进行本义。为此,在 Go 中,请在字符之前应用反斜杠 ()。例如,上面是应用转义字符的最常见示例:

  • n:新行
  • r:回车符
  • t:选项卡
  • ‘:单引号
  • “:双引号
  • :反斜杠
    应用以下代码片段来测试转义字符:
`fullName := "John Doe t(alias"Foo")n"
println(fullName)` 

你应会看到以下输入(包含新行):

`John Doe        (alias "Foo")` 

默认值

到目前为止,简直每次申明变量时,都应用值对其进行了初始化。但与在其余编程语言中不同的是,在 Go 中,如果你不对变量初始化,所有数据类型都有默认值。此性能十分不便,因为在应用之前,你无需查看变量是否已初始化。

上面列出了咱们目前浏览过类型的几个默认值:

  • int 类型的 0(及其所有子类型,如 int64)
  • float32float64 类型的 +0.000000e+000
  • bool 类型的 false
  • string 类型的空值
    运行以下代码片段以确认后面列出的默认值:
`var defaultInt int
var defaultFloat32 float32
var defaultFloat64 float64
var defaultBool bool
var defaultString string
println(defaultInt, defaultBool, defaultFloat32, defaultFloat64, defaultString)` 

你能够应用相似于此代码的代码来确定咱们没有浏览到的数据类型默认值。

类型转换

在上一节中,咱们确认在 Go 中隐式强制转换不起作用。接下来,须要显式强制转换。Go 提供了将一种数据类型转换为另一种数据类型的一些本机办法。例如,一种办法是对每个类型应用内置函数,如下所示:

`var integer16 int16 = 127
var integer32 int32 = 32767
println(int32(integer16) + integer32)` 

Go 的另一种转换方法是应用 strconv 包。例如,若要将 string 转换为 int,能够应用以下代码,反之亦然:

`package main

import "strconv"

func main() {i, _ := strconv.Atoi("-42")
    s := strconv.Itoa(-42)
    println(i, s)
}` 

运行后面的代码,并确认它运行并打印 -42 两次。

请留神,在后面的代码中,有一个下划线 (_) 用作变量的名称。在 Go 中,这意味着咱们不会应用该变量的值,而是要将其疏忽。否则,程序将不会进行编译,因为咱们须要应用申明的所有变量。咱们将返回到本主题,届时你将在后续模块中理解 _ 通常示意的内容。

创立函数

在 Go 中,函数容许你将一组能够从应用程序的其余局部调用的语句组合在一起。你能够应用函数来组织代码并使其更易于浏览,而不是创立蕴含许多语句的程序。更具可读性的代码也更易于保护。

到目前为止,咱们始终在调用 println() 函数,并且在 main() 函数中编写代码。在本节中,咱们将探讨如何创立自定义函数。咱们还将介绍一些可用于 Go 函数的其余技巧。

main 函数

与之交互的函数是 main() 函数。Go 中的所有可执行程序都具备此函数,因为它是程序的终点。你的程序中只能有一个 main() 函数。如果创立的是 Go 包,则无需编写 main() 函数。咱们将在后续模块中介绍如何创立包。

在深刻理解如何创立自定义函数的基本知识之前,让咱们看看 main() 函数的一个重要个性。你可能留意到,main() 函数没有任何参数,并且不返回任何内容。但这并不意味着其不能从用户读取值,如命令行参数。如要拜访 Go 中的命令行参数,能够应用用于保留传递到程序的所有参数的 os 包 和 os.Args 变量来执行操作。

上面的代码从命令行读取两个数字,并为其求和:

`package main

import (
    "os"
    "strconv"
)

func main() {number1, _ := strconv.Atoi(os.Args[1])
    number2, _ := strconv.Atoi(os.Args[2])
    println("Sum:", number1+number2)
}` 

os.Args 变量蕴含传递给程序的每个命令行参数。因为这些值的类型为 string,因而须要将它们转换为 int 以进行求和。

若要运行程序,请应用以下命令:

`go run main.go 3 5` 

输入如下:

`Sum: 8` 

让咱们看看如何重构上述代码,并创立第一个自定义函数。

自定义函数

上面是用于创立函数的语法:

`func name(parameters) (results) {body-content}` 

请留神,应用 func 关键字来定义函数,而后为其指定名称。在命名后,指定函数的参数列表。你能够指定零个或多个参数。你还能够定义函数的返回类型,该函数也能够是零个或多个。(咱们将在下一节中探讨如何返回多个值)。在定义所有这些值之后,你能够编写函数的注释内容。

若要练习此技巧,咱们将重构上一节的代码,为自定义函数中的数字求和。咱们将应用以下代码:

`package main

import (
    "os"
    "strconv"
)

func main() {sum := sum(os.Args[1], os.Args[2])
    println("Sum:", sum)
}

func sum(number1 string, number2 string) int {int1, _ := strconv.Atoi(number1)
    int2, _ := strconv.Atoi(number2)
    return int1 + int2
}` 

此代码创立一个名为 sum 的函数,该函数采纳两个 string 参数,并将它们强制转换为 int,而后返回求和所得的后果。定义返回类型时,函数须要返回该类型的值。

在 Go 中,你还能够为函数的返回值设置名称,将其当作一个变量。例如,你能够重构如下 sum 函数:

`func sum(number1 string, number2 string) (result int) {int1, _ := strconv.Atoi(number1)
    int2, _ := strconv.Atoi(number2)
    result = int1 + int2
    return
}` 

请留神,你当初须要将函数的后果值括在括号中。你还能够在函数中应用该变量,并且只需在开端增加 return 行。Go 将返回这些返回变量的以后值。在函数开端编写 return 关键字非常简单不便,尤其是在有多个返回值时。但咱们不倡议采纳这种办法,因为它不太分明函数返回的内容。

返回多个值

在 Go 中,函数能够返回多个值。你能够采纳相似于定义函数参数的形式来定义这些值。换句话说,你能够指定一个类型和名称,但该名称是可选的。

例如,假如你想要创立一个函数,以将两个数字求和,又让它们相乘。函数代码将如下所示:

`func calc(number1 string, number2 string) (sum int, mul int) {int1, _ := strconv.Atoi(number1)
    int2, _ := strconv.Atoi(number2)
    sum = int1 + int2
    mul = int1 * int2
    return
}` 

你当初须要两个变量来存储函数的后果。(否则就不会进行编译。)它的外观如下所示:

`func main() {sum, mul := calc(os.Args[1], os.Args[2])
    println("Sum:", sum)
    println("Mul:", mul)
}` 

Go 的另一个乏味性能是,如果不须要函数的某个返回值,能够通过将返回值调配给 _ 变量来放弃该函数。_ 变量是 Go 疏忽返回值的习用形式。它容许程序进行编译。因而,如果只须要求和,则能够应用以下代码:

`func main() {sum, _ := calc(os.Args[1], os.Args[2])
    println("Sum:", sum)
}` 

在后续模块中探讨错误处理时,咱们将具体介绍如何疏忽函数的返回值。

更改函数参数值(指针)

将值传递给函数时,该函数中的每个更改都不会影响调用方。Go 是“按值传递”编程语言。这意味着每次向函数传递值时,Go 都会应用该值并创立本地正本(内存中的新变量)。在函数中对该变量所做的更改都不会影响你向函数发送的更改。

例如,假如你创立了一个用于更新人员姓名的函数。请留神,运行此代码时会产生的变动:

`package main

func main() {
    firstName := "John"
    updateName(firstName)
    println(firstName)
}

func updateName(name string) {name = "David"}` 

即便你在函数中将该名称更改为 David,输入仍为 John。因为 updateName 函数中的更改仅会批改本地正本,因而输入不会发生变化。Go 传递变量的值,而不是变量自身。

如果你心愿在 updateName 函数中进行的更改会影响 main 函数中的 firstName 变量,则须要应用指针。指针 是蕴含另一个变量的内存地址的变量。当你发送指向某个函数的指针时,不会传递值,而是传递地址内存。因而,对该变量所做的每个更改都会影响调用方。

在 Go 中,有两个运算符可用于解决指针:

  • & 运算符应用其后对象的地址。
    • 运算符勾销援用指针。也就是说,你能够返回指针中蕴含的地址拜访其中的对象。

让咱们批改后面的示例,以说明指针的工作形式:

`package main

func main() {
    firstName := "John"
    updateName(&firstName)
    println(firstName)
}

func updateName(name *string) {*name = "David"}` 

运行后面的代码。请留神,输入当初显示的是 David,而不是 John

首先要做的就是批改函数的签名,以指明你要接管指针。为此,请将参数类型从 string 更改为 *string。(后者仍是字符串,但当初它是指向字符串 的 指针。)而后,将新值调配给该变量时,须要在该变量的左侧增加星号 (*) 以暂停该变量的值。调用 updateName 函数时,零碎不会发送值,而是发送变量的内存地址。这就是后面的代码在变量左侧带有 & 符号的起因。

理解包

Go 包与其余编程语言中的库或模块相似。你能够打包代码,并在其余地位重复使用它。包的源代码能够散布在多个 .go 文件中。到目前为止,咱们已编写 main 包,并对其余本地包进行了一些援用。

在本节中,你将理解什么是包。你还将理解如何创立一个包,以及如何应用内部包。

main 包

你可能留神到,在 Go 中,甚至最间接的程序都是包的一部分。通常状况下,默认包是 main 包,即目前为止始终应用的包。如果程序是 main 包的一部分,Go 会生成二进制文件。运行该文件时,它将调用 main() 函数。

换句话说,当你应用 main 包时,程序将生成独立的可执行文件。但当程序非是 main 包的一部分时,Go 不会生成二进制文件。它生成包存档文件(扩大名为 .a 的文件)。

依照约定,包名称与导入门路的最初一个元素雷同。例如,若要导入 math/rand 包,须要按如下形式将其导入:

`import "math/rand"` 

若要援用包中的对象,请执行如下操作:

`rand.Int()` 

让咱们创立包。

创立包

在名为 calculator 的 $GOPATH/src 目录中创立新目录。创立名为 sum.go 的文件。树目录应如下列目录所示:

`src/
  calculator/
    sum.go` 

用包的名称初始化 sum.go 文件:

`package calculator` 

你当初能够开始编写包的函数和变量。不同于其余编程语言,Go 不会提供 publicprivate 关键字,以批示是否能够从包的内外部调用变量或函数。但 Go 须遵循以下两个简略规定:

  • 如需将某些内容设为专用内容,请以小写字母开始。
  • 如需将某些内容设为公共内容,请以大写字母开始。

接下来,让咱们将以下代码增加到咱们要创立的计算器包:

`package calculator

var logMessage = "[LOG]"

// Version of the calculator
var Version = "1.0"

func internalSum(number int) int {return number - 1}

// Sum two integer numbers
func Sum(number1, number2 int) int {return number1 + number2}` 

让咱们看一下该代码中的一些事项:

  • 只能从包内调用 logMessage 变量。
  • 能够从任何地位拜访 Version 变量。倡议你增加正文来形容此变量的用处。(此形容实用于包的任何用户。)
  • 只能从包内调用 internalSum 函数。
  • 能够从任何地位拜访 Sum 函数。倡议你增加正文来形容此函数的用处。
  • 若要确认一切正常,可在 calculator 目录中运行 go build 命令。如果执行此操作,请留神零碎不会生成可执行的二进制文件。

创立模块

已将计算器性能组合到包中。当初能够将包组合到模块中。为什么?包的模块指定了 Go 运行已组合代码所需的上下文。此上下文信息包含编写代码时所用的 Go 版本。

此外,模块还有助于其余开发人员援用代码的特定版本,并更轻松地解决依赖项。另一个长处是,咱们的程序源代码无需严格存在于 $GOPATH/src 目录中。如果开释该限度,则能够更不便地在其余我的项目中同时应用不同包版本。

因而,若要为 calculator 包创立模块,请在根目录 ($GOPATH/src/calculator) 中运行以下命令:

`go mod init github.com/myuser/calculator` 

运行此命令后,github.com/myuser/calculator 就会变成包的名称。在其余程序中,你将应用该名称进行援用。命令还会创立一个名为 go.mod 的新文件。最初,树目录现会如下列目录所示:

`src/
  calculator/
    go.mod
    sum.go` 

该文件的 go.mod 内容应该如下代码所示:(Go 版本可能不同。)

`module github.com/myuser/calculator

go 1.14` 

若要在其余程序中援用此包,须要应用模块名称进行导入。在这种状况下,其名称为 github.com/myuser/calculator。当初,让咱们看一下示例,理解如何应用此包。

备注: 过来,治理 Go 中的依赖项并不容易。依赖关系管理系统仍在进行中。如果你想要理解无关模块的详细信息,请 [参阅 Go 博客](https://blog.golang.org/using-go-modules) 中公布的系列帖子。

援用本地包(模块)

当初,让咱们先应用包。咱们将持续应用咱们始终应用的示例应用程序。这一次,咱们将应用之前在 calculator 包中创立的函数,而不是 main 包中的 sum 函数。

树文件构造现应如下所示:

`src/
  calculator/
    go.mod
    sum.go
  helloworld/
    main.go` 

咱们会将此代码用于 $GOPATH/src/helloworld/main.go 文件:

`package main

import "github.com/myuser/calculator"

func main() {total := calculator.Sum(3, 5)
    println(total)
    println("Version:", calculator.Version)
}` 

请留神,import 语句应用所创立包的名称:calculator。若要从该包调用 Sum 函数,你须要将包名称指定为 calculator.Sum。最初,你现还可拜访 Version 变量。请按调用以下内容:calculator.Version

如果立刻尝试运行程序,它将不起任何作用。你须要告诉 Go,你会应用模块来援用其余包。为此,请在 $GOPATH/src/helloworld 目录中运行以下命令:

`go mod init helloworld` 

在上述命令中,helloworld 是项目名称。此命令会创立一个新的 go.mod 文件,因而,树目录会如下所示:

`src/
  calculator/
    go.mod
    sum.go
  helloworld/
    go.mod
    main.go` 

如果关上 go.mod 文件,则应看到相似于上面代码的内容:(Go 版本可能不同。)

`module helloworld

go 1.14` 

因为你援用的是该模块的本地正本,因而你须要告诉 Go 不要应用近程地位。因而,你须要手动批改 go.mod 文件,使其蕴含援用,如下所示:

`module helloworld

go 1.14

require github.com/myuser/calculator v0.0.0

replace github.com/myuser/calculator => ../calculator` 

replace 关键字指定应用本地目录,而不是模块的近程地位。在这种状况下,因为 helloworldcalculator 程序在 $GOPATH/src 中,因而地位只能是 …/calculator。如果模块源位于不同的地位,请在此处定义本地门路。

应用以下命令运行程序:

`go run main.go` 

零碎应输入如下内容:

`8
Version:  1.0` 

挑战 1:
如果尝试从主应用程序中的 calculator 包调用 logMessage 变量或 internalSum 函数,会产生什么?它是否运行?试一试吧!

质询解决方案:

`package main

import "github.com/myuser/calculator"

func main() {total := calculator.internalSum(5)
    println(total)
    println("Version:", calculator.logMessage)
}` 

公布包

你能够轻松公布 Go 包。只需公开提供包源代码即可实现。大多数开发人员都应用 GitHub 公开公布包。这就是为什么有时会在 import 语句中找到对 github.com 的援用。

例如,如果想要将 calculator 包公布到 GitHub 帐户,则须要创立一个名为 calculator 的存储库。URL 应与下述网址相似:

`https://github.com/myuser/calculator` 

你将通过标记存储库来对包进行版本化,如下所示:

`git tag v0.1.0
git push origin v0.1.0` 

如果是想要应用你的包的开发人员(包含你本人)援用如下所述内容:

`import "github.com/myuser/calculator"` 

让咱们更具体地探讨如何援用第三方包。

援用内部(第三方)包

有时,程序须要援用其余开发人员编写的包。你通常能够在 GitHub 上找到这些包。不管你是要开发包(非 main 包)还是独立的程序(main 包),以下无关援用第三方包的阐明均实用。

让咱们增加对 rsc.io/quote 包的援用:

`package main

import (
    "github.com/myuser/calculator"
    "rsc.io/quote"
)

func main() {total := calculator.Sum(3, 5)
    println(total)
    println("Version:", calculator.Version)
    println(quote.Hello())
}` 

如果应用 Visual Studio Code,则保留文件时将更新 go.mod 文件。当初它的外观如下所示:

`module helloworld

go 1.14

require (
    github.com/myuser/calculator v0.0.0
    rsc.io/quote v1.5.2
)

replace github.com/myuser/calculator => ../calculator` 

请留神 rsc.io/quote 如何援用特定包版本。如果须要降级程序的依赖项,则须要在此处更改版本。

应用以下命令再次运行程序:

`go run main.go` 

输入应如下所示:

`8
Version:  1.0
Hello, world.` 

日后对第三方包的所有援用都须要蕴含在 go.mod 文件中。运行或编译应用程序时,Go 将下载其所有依赖项。

总结

咱们介绍了开始在 Go 中构建更简单应用程序所需的基础知识。当初,你能够通过几种办法来申明和初始化变量。你还理解 Go 提供的各种数据类型。你曾经应用最根本的数据类型,

并且还理解到如何创立函数来组织代码,并使代码更易于保护。你曾经理解到,Go 是“按值传递”语言,但它亦反对指针。咱们将在后续的局部模块中应用指针。

最初,你曾经理解包在 Go 中的工作原理,以及如何在须要与其余开发人员共享代码时创立模块。你曾经理解到,如果只须要创立独立的应用程序,则所有代码都须要成为 main 包的一部分。你曾经理解到,该程序的终点是 main() 函数。当初,你已理解如何援用本地和第三方模块。构建 Go 程序时,你将会应用这些模块。

本文转自:SDK 社区(sdk.cn)是一个中立的社区,这里有多样的前端常识,有丰盛的 api,有爱学习的人工智能开发者,有有趣风趣的开发者带你学 python,还有将来炽热的鸿蒙,当各种元素组合在一起,让咱们一起脑洞大开独特打造业余、好玩、有价值的开发者社区,帮忙开发者实现自我价值!

退出移动版