Go基础语法


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