Go基础知识(一)
Go命令行和项目结构
Go的工作区目录结构有bin、pkg、src三个(在GOPATH目录下):
-
bin:编译后的可执行程序的存储目录。
-
pkg:编译时生成的对象文件。
-
src:库文件。
这些都是Go设计者的约定,只需按照这样的方式组织目录结构即可。
GOPATH环境变量生效时个人项目可以在src目录下创建新目录,第三方库存放在src的github.com目录下。
Go版本1.11以上支持设置GOROOT环境变量,在任意目录下创建项目程序即可。安装Go语言开发系统后,内置的命令行工具常用的命令如下:
go build:将程序编译成可执行文件。
go run:将程序先编译成可执行文件,再运行程序。
go fmt:格式化代码,比如换行、缩进等。
go test:运行测试的命令。
go get:下载第三方库的常用命令。
go version:查看当前操作系统中安装的Go语言系统的版本信息。
go env:查看当前操作系统和Go语言相关的环境变量的值。
Go语言的基本语法
变量
变量、常量:定义好需要操作的对象。
任何语言都有一套自己的命名规则,比如Python建议使用带下画线的命名规则,如number_list,而Go建议使用驼峰式命名规则,如numberList。
但在Go中建议仅使用字母为变量命名,其实很简单,使用描述变量含义的英文单词即可。
声明与赋值
package main
import "fmt"
func main() {
var numberOne int
numberOne = 1
numberTwo := 2
var isNumber bool
isNumber = true
canFly := false
var numberMax float64
numberMax = 1.23
numberMin := 3.1415
strOne, strTwo, strThree := "1", "2", "3"
fmt.Println(numberOne)
fmt.Println(numberTwo)
fmt.Println(isNumber)
fmt.Println(isNumber, canFly)
fmt.Println(numberMax, numberMin)
fmt.Println(strOne, strTwo, strThree)
}
PS D:\go\src\helloworld> go run .\main.go
1
2
true
true false
1.23 3.1415
1 2 3
变量的声明使用Go内置的关键字var,可以显式地声明变量的数据类型(比如numberOne、isNumber、numberMax),也可以在声明变量的同时赋值(比如numberTwo、canFly、numberMin),具体的数据类型由编译器自动识别。
常量
变量是运行过程中其值会变动的量,所以一般不适合把变量的作用域设置为全局作用域,如果项目复杂,要多次使用这个变量的值,在运行过程中这个变量的值可能会发生变动,因而对这个变量的追踪不是很容易。
因此,要尽量避免使用全局变量。相对于变量,还存在一种不会变动的量,称之为常量。因为常量的值不会在运行过程中变动,所以更适用于全局作用域。
基本数据类型
序号 | 类型和描述 |
---|---|
1 | 布尔型 布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 |
2 | 数字类型 整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。 |
3 | 字符串类型: 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。 |
4 | 派生类型: 包括:(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型 |
数值类型
数值类型分为整数类型和浮点类型,整数类型相应地又可细分为有符号类型和无符号类型。数值类型根据数据存储空间的大小,可分为如下几种:
整数
序号 | 类型和描述 |
---|---|
1 | uint8 无符号 8 位整型 (0 到 255) |
2 | uint16 无符号 16 位整型 (0 到 65535) |
3 | uint32 无符号 32 位整型 (0 到 4294967295) |
4 | uint64 无符号 64 位整型 (0 到 18446744073709551615) |
5 | int8 有符号 8 位整型 (-128 到 127) |
6 | int16 有符号 16 位整型 (-32768 到 32767) |
7 | int32 有符号 32 位整型 (-2147483648 到 2147483647) |
8 | int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
浮点型
序号 | 类型和描述 |
---|---|
1 | float32 IEEE-754 32位浮点型数 |
2 | float64 IEEE-754 64位浮点型数 |
3 | complex64 32 位实数和虚数 |
4 | complex128 64 位实数和虚数 |
其他数字类型
以下列出了其他更多的数字类型:
序号 | 类型和描述 |
---|---|
1 | byte 类似 uint8 |
2 | rune 类似 int32 |
3 | uint 32 或 64 位 |
4 | int 与 uint 一样大小 |
5 | uintptr 无符号整型,用于存放一个指针 |
字符串类型
字符类型是一种常见的基本数据类型,包括:
string rune
数组类型
表示一组具有相同数据类型的数据集合,具有固定的长度:
package main
import "fmt"
func main() {
var numbers = [3]int{1,2,3}
fmt.Println(numbers)
}
------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
[1 2 3]
切片类型
表示一组具有相同数据类型的集合,但是长度不固定,可以扩充:
package main
import "fmt"
func main() {
var numbers = []int{1,2,3}
fmt.Println(numbers)
}
------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
[1 2 3]
结构体类型
表示一组具有不同数据类型的值的集合,基本定义和C语言中的结构体很像,但是用法和C语言的差别很大。
package main
import (
"fmt"
)
type Persion struct {
name string
age int8
sex string
}
func main() {
var tom Persion
tom.name = "Tom"
tom.age = 12
tom.sex = "男"
fmt.Println(tom)
}
-------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
{Tom 12 男}
函数类型
函数也可以表示为一种类型:
package main
import (
"fmt"
)
func main() {
var add = func(x int, y int) int {
return x + y
}
fmt.Println(add(1, 2))
}
--------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
3
interface
表示任意类型,也可以用来表示一系列方法的集合,定义方法的类型:
下面举个栗子:
用例:一个人,他的有两种角色,在公司是程序猿,在家里是孩他爸。在公司当程序猿时就写bug,在家当爹时就洗尿布。则其接口和结构体的映射关系为:
package main
import "fmt"
type CodeMonkey interface {
codingEveryday() string
}
type Parent interface {
washingDiaper() string
}
type Person struct {
id int
name string
}
func (self *Person) codingEveryday() string {
return fmt.Sprintf("user %d, %s write bug every day.", self.id, self.name)
}
func (self *Person) washingDiaper() string {
return fmt.Sprintf("user %d, %s take care of his baby.", self.id, self.name)
}
func main() {
var monkey CodeMonkey = &Person{1, "Tom"}
fmt.Println(monkey.codingEveryday())
var father Parent = &Person{2, "John"}
fmt.Println(father.washingDiaper())
}
----------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
user 1, Tom write bug every day.
user 2, John take care of his baby.
map
键值对(Key-Value Pair)形式的类型被称为map类型:
package main
import "fmt"
func main() {
stu := make(map[string]string)
stu["name"] = "tom"
stu["age"] = "18"
stu["sex"] = "男"
fmt.Println(stu["name"], stu["age"], stu["sex"])
}
-----------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
tom 18 男
channel
Go语言原生支持并发,数据之间使用channel(管道)来通信:
package main
import (
"fmt"
)
func main() {
var ch = make(chan string)
go func() {
ch <- "hello"
}()
fmt.Println(<-ch)
}
-----------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
hello
类型转换
Go是强数据类型的编程语言,并不是所有数据类型都可以直接进行相互转换,可以使用内置的标准库strconv来完成字符串类型和数值类型、布尔类型之间的类型转换。
package main
import (
"fmt"
"strconv"
)
func main() {
// 数字转化为字符串
numbser := 100
fmt.Println(numbser + 1)
fmt.Println(strconv.Itoa(numbser) + "1")
// 布尔类型转换为字符串
isNumbser := true
fmt.Println(strconv.FormatBool(isNumbser))
}
-------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
101
1001
true
自定义类型Go语言支持用户自定义类型,不过这些类型都是从基本数据类型派生出来的,也就是说自定义类型是由内置的基本数据类型组合而成的。
type INT int //INT 是一个使用预声明类型声明的自定义类型
type Map map[string]string //Map 是一个使用类型字面量声明的自定义类型
type myMap Map //myMap 是一个自定义类型Map 声明的自定义类型
// INT, Map ,myMap 都是命名类型
函数
函数是结构化编程最小的单元,将一些程序代码片段集合起来完成特定的任务,便于程序代码的复用和程序逻辑的组织。
package main
import (
"fmt"
)
func PrintUserInfo(user map[string]string){
fmt.Println(user["name"])
fmt.Println(user["age"])
fmt.Println(user["sex"])
}
func main() {
stu := make(map[string]string)
stu["name"] = "tom"
stu["age"] = "18"
stu["sex"] = "男"
PrintUserInfo(stu)
}
PS D:\go\src\helloworld> go run .\main.go
tom
18
男
1)以关键字func开头定义一个函数,可以有传入参数,也可以没有传入参数,可以有返回值,也可以没有返回值。
2)不以func开头也可以定义一个函数,称为匿名函数。赋予一个变量,通过该变量即可调用匿名函数,匿名函数多用于简单的处理逻辑。
3)函数调用需要带上“( )”。
4)返回值使用关键字return。
5)函数名称大写,表示可导出;小写则表示私有,不可导出(即不同程序包之间是否可以调用或者引用)。
Go是强类型的编程语言,输入参数后,返回值都需要指定数据类型。具有多个返回值需要带“( )”,比如(int, string)。函数调用时参数的顺序要和定义参数时保持一致。有几个输入参数,就要传入几个输入参数;有几个返回值,就要接收几个返回值。
package main
import (
"fmt"
"strconv"
)
func MultiResult(numberOne, numberTwo int) (int, string) {
num := numberOne + numberTwo
return num, strconv.Itoa(num)
}
func main() {
fmt.Println(MultiResult(100, 200))
}
---------------------------------------------------------------------
PS D:\go\src\helloworld> go run .\main.go
300 300
匿名函数
简而言之,匿名函数是指没有指定名称的函数,一般用于处理逻辑比较简单的场合。
package main
import (
"fmt"
)
func main() {
add := func(x, y int) int {
return x + y
}
fmt.Println(add(1, 2))
}