这篇文章来讲下Go语言的基础内容,整体包括golang初识,golang的第一个程序,go项目的编译和构建,最后就是go语言的基础知识(一些语法基础)
golang初识 :
golang没有那些内容:
- 没有类(class) : 用结构体替代
- 没有方法重载
- 没有继承
- 没有枚举类型
- 没有try/catch
- 没有泛型
golang有什么:
- struct(结构体)
- 结构体的内嵌
- 常量
- defer/recover/panic
- interface{}
- 接口
golang特性 :
- 头等函数,允许将函数分配给变量,作为其他函数的入参,返回值,函数可以是对象,函数也可以是类型
- 并行操作非常方便,通过go关键字启动协程
- 通过通讯共享内容
- 多路复用,channel的多路复用
golang语言特性
Golang的优势
极简单的部署方式:可直接编译成机器码、不依赖其他库、直接运行即可部署。
静态类型语言,编译的时候可以检查出大多数问题。
语言层面的并发:天生的基因支持、充分的利用多核
// Go 语言实现并发的代码
func goFunc(i int) {
fmt.Println("goroutine ", i, " ...")
}
func main() {
for i := 0; i < 1000; i++ {
go goFunc(i) // 开启一个并发协程
}
time.Sleep(time.Second)
}
强大的标准库
runtime 系统调度机制、高效的 CG 垃圾回收、丰富的标准库
Golang 的应用场景
1、云计算基础设施领域:
代表项目:docker、kubernetes、etcd、consul、cloud flare CDN、七牛云存储 等。
2、基础后端软件:
代表项目:tidb、influxdb、 cockroach 等。
3、微服务
代表项目:go-kit、 micro、 monzo bank 的 typhon、bilibili 等。
4、互联网基础设施
代表项目:以太坊、hyperledger 等。
有编程经验如何快速学习go
- 那些内容是golang没有的
- 使用golang的特性的替代方案
- golang面向对象编程
- golang多态的实现
golang的第一个程序 :
// hello.go
package main // 在go中,每个文件都必须归属于一个包
import "fmt" //引入一个包,包名fmt,引入该包后,就可以使用fmt包的函数,比如fmt.Println()
func main() { // func 是一个关键字,表示一个函数,main是函数名,是我们程序的入口
fmt.Println("Hello World!")//调用fmt包中的函数Println()输出Hello World
}
变量
-
Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
-
Go语言是一门强类型语言,每一个变量都有它自己的变量类型
-
常见的变量类型
- 字符串
- 浮点型
- 整数型
- 布尔型
-
变量声明
-
指定变量类型,如果没有初始化,则变量默认为零值。
go 复制代码 /* var v_name v_type //声明变量 v_name = value //赋值 */ var t1 string = "hello" var t2 int = 1 var t3 bool = true -
根据值自行判定变量类型。
go 复制代码 /* var v_name = value */ var t1 = "hello" var t2 = 1 var t3 = true -
使用 := 声明变量
go 复制代码 /* v_name := value */ t1 := "hello" t2 := 1 t3 := true -
多变量声明
go 复制代码 //类型相同多个变量, 非全局变量 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3 var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断 vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误 // 这种因式分解关键字的写法一般用于声明全局变量 var ( vname1 v_type1 vname2 v_type2 )
-
常量
-
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
-
常量的定义格式
go 复制代码 /* const identifier [type] = value */ // 显式类型定义: const t1 string = "abc" // 隐式类型定义: const t2 = "abc" // 多个相同类型的声明 const c_name1, c_name2 = value1, value2 -
常量还可以用作枚举
go 复制代码 const ( t1 = iota t2 = 1 t3 = 2 )iota,特殊常量,可以认为是一个可以被编译器修改的常量。第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1
常用的数据类型
-
整数,int
支持的整型分类很细,主要差异是占用的存储空间不同。基于有无符号列出为:
- 有符号的:int,int8,int16,int32,int64
- 无符号的:uint,uint8,uint16,uint32,uint64
其中int, unit是基于处理器架构的。意味着会根据处理器来确定是32bit还是64bit。 使用时,常常使用int。或者使用int32保证兼容。 在类型推导时,推导的整型为int,其他长度整型需要在定义变量时强制声明。(整型的默认值为0)
-
浮点数,float
支持IEEE-754标准浮点数。支持32bit和64bit的浮点数float32和float64。 在类型推导时,推导的浮点型为float64。float32需要在定义变量时强制声明。(浮点数的默认值为0)
-
复数,complex
原生支持复数。 支持32bit+32bit复数complex64,和64bit+64bit的复数complex128。
go 复制代码 // 定义复数 var t1 complex64 = complex(1, 2) var t2 complex128 = complex(1, 2) t3 := 1 + 2i t4 := complex(float64(1), float64(2)) // 获取实部和虚部 realPart := real(t1) imagPart := imag(t2) -
字符串,string
原生支持字符串。使用双引号("")或反引号(
)定义,内部是utf-8编码。 双引号:"", 用于单行字符串。 反引号:,用于定义多行字符串,内部会原样解析。 示例:text 复制代码 // 单行 "test" // 多行 ` test test `字符串支持转义字符,列表如下: \r 回车符(返回行首) \n 换行符(直接跳到下一行的同列位置) \t 制表符 ' 单引号 " 双引号 \ 反斜杠 * \uXXXX Unicode字符码值转义
-
布尔型,bool
布尔型的值只可以是常量 true 或者 false
-
指针,pointer
指针类型用于存储变量地址。使用运算符
&,*完成操作。 使用运算符p:=&v可以获取v变量的地址。p中的数据格式类似0xc0000b9528,是一个内存地址的16进制表示。 使用运算符*p可以获取指针p指向变量v的值。在Go语言中,指针主要用于: 类型指针,对指针指向的数据进行修改。函数调用时传递参数使用指针,避免值传递拷贝额外数据。注意类型指针不能进行偏移和运算。 切片,由指向起始元素的原始指针、元素数量和容量组成。
-
数组,array
数组是一段固定长度的连续内存区域。是具有相同类型数据元素序列。元素类型支持任意内置类型。 数组从声明时就确定长度,可以修改数组元素,但是数组不可修改长度。 使用
[长度]类型进行数组的声明。 示例:go 复制代码 // 默认值初始化 var nums [4]int // [0 0 0 0] // 数组常量初始化数组 var position = [4]string{"east", "south", "west", "north"} var arrAge = [5]int{18, 20, 15, 22, 16} var arrKeyValue = [5]string{3: "Chris", 4: "Ron"} // 自动确定长度 var position = [...]string{"east", "south", "west", "north"} -
切片,slice
-
切片可以看作是数组的引用,切片和数据对应的是同一份数据,如果原数组的数据发生变化,那么会连带着切片中的数据一起变化。
-
左闭右开
-
切片声明:var identifier []type
-
len()函数计算切片长度,cap()函数计算切片容量,append()函数进行切片追加,copy()函数进行拷贝
-
切片使用
-
从数组中产生切片
go 复制代码 var a [10]int var s []int= a[:] s = a[:4] s = a[1:] -
直接定义切片
go 复制代码 s := []int{1,2,3,4,5,6} -
make方法创建切片
go 复制代码 /* make 的使用方式是:func make([]T, len, cap),其中 cap 是可选参数。 */ s := make([]int, 0, 5)
-
-
二维切片
go 复制代码 mat := make([][]int, 10) for i := 0; i < 10; i++ { mat[i] = make([]int, 10) }
-
-
映射,map
-
Map 是一种无序的键值对的集合。
-
Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。
-
定义map
go 复制代码 /* 使用 make 函数 */ map_variable := make(map[KeyType]ValueType, initialCapacity)其中 KeyType 是键的类型,ValueType 是值的类型,initialCapacity 是可选的参数,用于指定 Map 的初始容量。Map 的容量是指 Map 中可以保存的键值对的数量,当 Map 中的键值对数量达到容量时,Map 会自动扩容。如果不指定 initialCapacity,Go 语言会根据实际情况选择一个合适的值。
-
获取元素:
go 复制代码 // 获取键值对 v1 := m["apple"] v2, ok := m["pear"] // 如果键不存在,ok 的值为 false,v2 的值为该类型的零值 -
修改元素:
go 复制代码 // 修改键值对 m["apple"] = 5 -
获取 Map 的长度:
go 复制代码 // 获取 Map 的长度 len := len(m) -
遍历 Map:
go 复制代码 // 遍历 Map for k, v := range m { fmt.Printf("key=%s, value=%d\n", k, v) } -
删除元素:
go 复制代码 // 删除键值对 delete(m, "banana")
-
-
结构体,struct
-
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。
-
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
-
定义结构体
结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:
text 复制代码 type struct_variable_type_name struct { member definition member definition ... member definition } -
结构体方法
Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收器(Receiver)
text 复制代码 func (接收器变量 接收器类型) 方法名(参数列表) (返回参数){ }接收器类型可以是带指针的与不带指针的,带指针的会对结构体修改
-
-
接口,interface
- interface 是方法声明的集合
- 任何类型的对象实现了在interface 接口中声明的全部方法,则表明该类型实现了该接口。
- interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。
- interface 可以被任意对象实现,一个类型/对象也可以实现多个 interface
-
interface 定义的方法不能重载,如 eat() eat(s string) 不能同时存在
text 复制代码 //Info 是一个接口,它有方法 Getinfo()string type Info interface { Getinfo() string }
-
函数,func()
-
函数定义
Go 语言函数定义格式如下:
text 复制代码 func function_name( [parameter list] ) [return_types] { 函数体 }
-
Go语言函数支持递归使用
条件语句
-
if语句
text 复制代码 if 布尔表达式 { ··· } -
if···else语句
text 复制代码 if 布尔表达式 { ··· }else 布尔表达式{ ··· } -
Switch语句
text 复制代码 switch var1 { case val1: ... case val2: ... default: ... }与C语言不同的是,Go语言中的switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case
循环语句
-
格式
go 复制代码 // 1、类似C语言的for循环 for init; condition; post { } // 2、类似C语言的while循环 for condition {} // 3、死循环 for {} // 4、可以使用for与range对 slice、map、数组、字符串等进行遍历 for key, value := range oldMap { newMap[key] = value }
- 与C语言类似可以使用break跳出循环,使用continue继续循环
总结
这篇文章是一次实践记录和工具使用练习,上述总结了go语言入门指南的大部分知识点