Go语言手册

发布时间 2023-06-08 16:45:59作者: Mugetsukun

(2023-6-8更新)

资料来源

Go 基础系列 | 骏马金龙
Go 语言教程 | runoob
Go语言学习 | rickiyang | cnblogs

基础知识

环境安装

(Ubuntu22.04 LTS)

sudo apt-get install && apt-get upgrade
sudo apt-get install golang

go version #安装后的版本查询

mkdir ~/workspace
echo 'export GOPATH="$HOME/workspace"' >> ~/.bashrc
source ~/.bashrc

结构

package main

import "fmt"

func main() {
	/*注释符号*/
	//花括号不能单独放行
   fmt.Println("Hello, World!")
}
// 单行注释
go run helloworld.go
  • 这个程序的第一行 package main 定义了这个文件属于 main 包。在 Go 语言中,每个程序都必须包含一个 main 包,并且在这个包下必须包含一个 main() 函数,作为程序的入口点。
  • 第三行 import "fmt" 引入了 fmt 包,这个包提供了格式化输入输出的函数。
  • 第五行 func main() { 定义了程序的入口点 main() 函数。
  • 第六行 fmt.Println("Hello, World!") 调用了 fmt 包中的 Println() 函数,用于输出一条字符串 "Hello, World!" 到标准输出设备上(通常是控制台)。
  • 最后一行 } 表示 main() 函数的结束。

Go 语言的基础组成有以下几个部分:

  • 包声明
  • 引入包
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释

标识符实际上就是一个或是多个字母(AZ和az)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

Go 语言的字符串连接可以通过 + 实现

Go 代码中会使用到的 25 个关键字或保留字:

break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

Go 语言还有 36 个预定义标识符:

append bool byte cap close complex complex64 complex128 uint16
copy false float32 float64 imag int int8 int16 uint32
int32 int64 iota len make new nil panic uint64
print println real recover string true uint uint8 uintptr

程序一般由关键字、常量、变量、运算符、类型和函数组成。
程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}。
程序中可能会使用到这些标点符号:.、,、;、: 和 …。

GO语言区分大小写

  • 任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则应该以小写字母开头。

  • 当命名(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Analysize,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);

  • 命名如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )

  • 包名应该为小写单词,不要使用下划线或者混合大小写。

文件命名
尽量采取有意义的文件名,简短,有意义,应该为小写单词,使用下划线分隔各个单词。
结构体命名采用驼峰命名法,首字母根据访问控制大写或者小写
struct 申明和初始化格式采用多行

type MainConfig struct {
    Port string `json:"port"`
    Address string `json:"address"`
}
config := MainConfig{"1234", "123.221.134"}

接口命名
命名规则基本和上面的结构体类型
单个函数的结构名以 “er” 作为后缀,例如 Reader , Writer 。

type Reader interface {
        Read(p []byte) (n int, err error)
}

变量命名
和结构体类似,变量名称一般遵循驼峰法,首字母根据访问控制原则大写或者小写,但遇到特有名词时,需要遵循以下规则:

  • 如果变量为私有,且特有名词为首个单词,则使用小写,如 appService
  • 若变量类型为 bool 类型,则名称应以 Has, Is, Can 或 Allow 开头
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool

常量均需使用全部大写字母组成,并使用下划线分词
const APP_URL = "https://www.baidu.com"

如果是枚举类型的常量,需要先创建相应类型:

type Scheme string

const (
    HTTP  Scheme = "http"
    HTTPS Scheme = "https"
)

格式化字符串
Go 语言中使用 fmt.Sprintf 或 fmt.Printf 格式化字符串并赋值给新串:

  • Sprintf 根据格式化参数生成格式化的字符串并返回该字符串。
  • Printf 根据格式化参数生成格式化的字符串并写入标准输出。
// 当前程序的包名
package main

// 导入其他包
import . "fmt"

// 常量定义
const PI = 3.14

// 全局变量的声明和赋值
var name = "gopher"

// 一般类型声明
type newType int

// 结构的声明
type gopher struct{}

// 接口的声明
type golang interface{}

// 由main函数作为程序入口点启动
func main() {
    Println("Hello World!")
}

错误处理

  • 错误处理的原则就是不能丢弃任何有返回err的调用,不要使用 _ 丢弃,必须全部处理。接收到错误,要么返回err,或者使用log记录下来
  • 尽早return:一旦有错误发生,马上返回
  • 尽量不要使用panic,除非你知道你在做什么
  • 错误描述如果是英文必须为小写,不需要标点结尾
  • 采用独立的错误流进行处理
// 错误写法
if err != nil {
    // error handling
} else {
    // normal code
}

// 正确写法
if err != nil {
    // error handling
    return // or continue, etc.
}
// normal code

常量

在程序编译阶段就确定下来的值,而程序在运行时无法改变该值。在Go程序中,常量可定义为数值、布尔值或字符串等类型。
const PI = 3.14

变量

//定义一个名称为“valName”,类型为"type"的变量
var valName type

//定义三个类型都是“type”的变量
var vname1, vname2, vname3 type

//定义三个类型都是"type"的变量,并且分别初始化为相应的值
//vname1为v1,vname2为v2,vname3为v3
var vname1, vname2, vname3 type= v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3
vname1, vname2, vname3 := v1, v2, v3
/*
:=这个符号直接取代了var和type,这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;
在函数外部使用则会无法编译通过,所以一般用var方式来定义全局变量。
*/

//_(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。在这个例子中,我们将值2赋予b,并同时丢弃1:
_, b := 1, 2

内置数据类型

Go 语言按类别有以下几种数据类型:

布尔型 --> 在Go中,布尔值的类型为bool,值只可以是常量 true 或者 false。一个简单的例子:var b bool = true
整数型 --> 整型 int 和浮点型 float,Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码;
字符串 --> 字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本;
派生型 -->
(a) 指针类型(Pointer)
(b) 数组类型
(c) 结构化类型(struct)
(d) 联合体类型 (union)
(e) 函数类型
(f) 切片类型
(g) 接口类型(interface)
(h) Map 类型
(i) Channel 类型

//Boolean
var isActive bool  // 全局变量声明
var enabled, disabled = true, false  // 忽略类型的声明
func test() {
    var available bool  // 一般声明
    valid := false      // 简短声明
    available = true    // 赋值操作
}
uint8 无符号 8 位整型 (0 到 255)
uint16 无符号 16 位整型 (0 到 65535)
uint32 无符号 32 位整型 (0 到 4294967295)
uint64 无符号 64 位整型 (0 到 18446744073709551615)
int8 有符号 8 位整型 (-128 到 127)
int16 有符号 16 位整型 (-32768 到 32767)
int32 有符号 32 位整型 (-2147483648 到 2147483647)
int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
float32 IEEE-754 32位浮点型数
float64 IEEE-754 64位浮点型数
complex64 32 位实数和虚数
complex128 64 位实数和虚数
byte 类似 uint8
rune 类似 int32
uint 32 或 64 位
int 与 uint 一样大小
uintptr 无符号整型,用于存放一个指针

iota枚举
这个关键字用来声明enum的时候采用,它默认开始值是0,const中每增加一行加1:

package main


const (
	x = iota // x == 0
	y
	z
	w 
)

const (
	h, i, j = iota, iota, iota //h=0,i=0,j=0 iota在同一行值相同
)

const (
	l       = iota //a=0
	m       = "B"
	n       = iota             //2
	o, p, q = iota, iota, iota //3,3,3
	r       = iota             //4
)

func main()  {
	println(x,y,z,w)
	println(h,i,j)
	println(l,m,n,o,p,q,r)
}

结果:
0 1 2 3
0 0 0
0 B 2 3 3 3 4