简介

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

.go

学习指标

在此模块中,你将:

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

先决条件

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

申明和应用变量

申明变量

var
`var firstName string` 
stringfirstName
`var firstName, lastName string` 
stringfirstNamelastNameint
`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
)` 
firstNamelastNamestringageint

通过多种形式初始化变量

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

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

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

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

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

(:=)
var

申明常量

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 有四类数据类型:

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

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

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

整数数字

intint8int16int32int648163264intuint8uint16uint32uint64

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

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

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

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

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

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

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

integer32integer64

质询解决方案:

`package main

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

质询解决方案:

`package main

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

浮点数字

float32float64
`var float32 float32 = 2147483647
var float64 float64 = 9223372036854775807
println(float32, float64)` 
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 会从应用的值推断其数据类型。

布尔型

truefalsebool01

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

`var featureFlag bool = true` 

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

字符串

stringstring(")(')runes

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

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

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

`John Doe        (alias "Foo")` 

默认值

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

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

intfloat32float64boolstring
`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)` 
strconvstringint
`package main

import "strconv"

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

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

(_)_
创立函数

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

println()main()

main 函数

main()main()main()
main()main()osos.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.Argsstringint

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

`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
}` 
sumstringint

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

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

返回多个值

在 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)
}` 
__
`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"
}` 
DavidJohnupdateName
updateNamemainfirstName

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

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

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

`package main

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

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

理解包

.gomain

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

main 包

mainmainmain()
mainmain
math/rand
`import "math/rand"` 

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

`rand.Int()` 

让咱们创立包。

创立包

sum.go
`src/
  calculator/
    sum.go` 
sum.go
`package calculator` 
publicprivate
  • 如需将某些内容设为专用内容,请以小写字母开始。
  • 如需将某些内容设为公共内容,请以大写字母开始。

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

`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
}` 

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

logMessageVersioninternalSumSumgo build

创立模块

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

$GOPATH/src
$GOPATH/src/calculator
`go mod init github.com/myuser/calculator` 
github.com/myuser/calculatorgo.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)中公布的系列帖子。

援用本地包(模块)

calculatormainsum

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

`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)
}` 
importcalculatorSumcalculator.SumVersioncalculator.Version
$GOPATH/src/helloworld
`go mod init helloworld` 

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

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

go 1.14` 
go.mod
`module helloworld

go 1.14

require github.com/myuser/calculator v0.0.0

replace github.com/myuser/calculator => ../calculator` 
replacehelloworldcalculator$GOPATH/src

应用以下命令运行程序:

`go run main.go` 

零碎应输入如下内容:

`8
Version:  1.0` 
calculatorlogMessageinternalSum

质询解决方案:

`package main

import "github.com/myuser/calculator"

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

公布包

GitHubimportgithub.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"` 

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

援用内部(第三方)包

GitHubmain
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 是“按值传递”语言,但它亦反对指针。 咱们将在后续的局部模块中应用指针。

mainmain()

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