1.基本的编程知识
高级编程语言大多数都有变量、三大结构(循环、循序、选择)以及函数概念。这些是编程的基本概念。是我们入门任何一中编程语言的第一部分。下面我将从这三种概念来学习golang。
1.1 变量
在golang 中数据类型有以下这些。
| 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
var count int = 10
// 等价于下面这种方式 声明和赋值 两个过程
var cnt int //声明
cnt = 10 //赋值
// 2
a := 10
第一种方法是一种比较常见的声明方式,常常用于我们只知道数据类型,但是不知道,数据类型中的数值是多少。当我们声明一个变量时,系统会给赋值为给定类型的0值,例如数值类型为0,指针类型为1。第二种常常用于我们接受函数的返回值。
1.2三大结构
顺序结构: 我们编程的最基本的结构,程序会阿按照我们的代码顺序执行,当然如果代码不影响我们的程序的正确的输出,编译器会进行指令重排。这个不是我们入门时要关注的。
循环结构: 在c中最为出名的结构就是for和while以及do while。在go中,循环结构,常常表现这种形式。
//死循环
for {
...
}
//遍历可迭代对象的循环
var array = []int{1,2,3,4,5,6};
for idx,val := range array {
...
}
//以及最经典的for 循环
for i:= 0;i<10;i++ {
...
}
在循环中我们依然可以用break和continue来推出当前循环和本轮循环。
以及选择结构:
//switch
switch var {
case 100:
...
case 90,80,70,60:
...
default:
...
}
//if else
if var == 100 {
} else if var >=60 {
} else {
}
需要注意的是,golang中的 { 不能作为一行的开始,这就需要我们要求我们必须注意我们的代码格式。
1.3函数
在golang中,函数的定义如下:
func div(var1 int,var2 int)(int,error){//没有返回值,就不写返回类型
if var2 == 0{
return 0,errors.New("can`t div with 0")
}else{
return var1/var2 nil
}
}
//其中nil表示空,如果一个函数没有错误,并要求返回值时,我们就常常返回一个空。另外nil也表示空pointer。
上述函数声明我们可以知道了如何声明一个函数。同时知道了func可以返回多个变量。
我们都知道不要返回局部变量的指针和引用,因为他们被返回后,被指向的变量就已经失效了。但是golang可以,因为编译器会帮我们将变量转移到heap区中。还有gc会帮我们完成内存的清理工作。
2.数组、切片、指针以及结构体
2.1 从数组到指针
我们声明数组时,它在计算机会这样表示。
var arr = [4]int {1,2,3,4}
程序会在stack中分配连续的4x4Byte的内存地址,并将变量赋值。但是我们要注意,如果要以数组作为参数为函数赋值,我们无法在函数中,修改对应的数组,因为golang 传递函数是传递整个数据结构。也就是新开辟一个stack保存函数的调用stack。那么这样不仅耗费巨大,而且还不能修改对应的数组。
那么我们有一种新的数据结构----切片。
切片是指向原数组的(收集器),本质是指针。
常用的声明有这样
arrSlice1 = arr[:] {1,2,3,4}
arrSlice2 = arr[1:4] {2,3,4}
既然切片本质上是指针那么就可以解决上面的问题。
//go也是通过 &*来从普通变量得到指针和解引用的。
例如
age := 10
pAge = &age
*age = 11
我们通过new函数可以将对应的变量开辟到heap区中。返回对应函数的指针。
make函数可以帮助我们在heap中开辟一个切片。
例如:
type struct People {
Age int
Name string
}
abc = new(People)
arr = make([]string,10)
上述过程中,我们定一了一个结构体People,通过new开辟的一个People类型的空间,以及使用make函数开辟了长度为10的string数组的切片。
如果你熟悉面向对象编程,你会发现在golang中并没有类。但是golang中也提供结构体方法。
例如
func (p People) sayHello(){
fmt.Println("hello ",p.Name)
}
除此之外,你会发现,如果在结构体中将对应字段的首字母改成小写。那么编译器会报错。这是因为在golang中编译器会根据首字母大小写来判断是否对外界暴露变量。
tag是go中的一个特性,这个特性可以帮助我们完成许多事情。例如自动帮我们解析json格式数据。
type Student struct{
ID int64 `json:"id"`
Name string `json:"name"`
}
//那么我们就可以使用json.Marshal(xxx)直接将结构体解析成对应json的数据结构。
p := Student{
ID:10,
Name:"lisan",
}
data,err := json.Marshal(p)
{"id":10,"name":"lisan"}
2.2继承去那了?
在go中没有继承,取而代之的是组合。
例如:
type People struct {
Name string
Age 12
}
func (p *People)XXX(){
...
}
type Student struct {
People
ID int64
}
stu := Student{
People {
xxx
},
xxx
}
stu.XXX()
上述过程中就是组成,通过组成我们可以使用对应组成对象的方法。
2.3鸭子类型和接口
什么是鸭子类型,如果一个变量有鸭子这种类型的所有方法,那么他就是鸭子。
在go中,interface就是来描述鸭子类型。如果一个变量实现了某个接口的所有方法,那么我们就可以使用这个接口类型来替代原有的类型。通过这种方式表现出多态。
type Speaker interface {
speak()
}
type People struct {
}
func (p *People)speak(){
...
fmt.Println("i am here")
}
var s Speaker = People{}
s.speaker()
// stdout: i am here
其中我们最常用的是空接口,在go的1.18 这个空接口有个别名为Any
他的定义如下:
type any inteface{}
既然空接口没有方法,那么我们可以使用any来接受任意类型的数据,也就是说我们可以使用空接口当作范型来用。
今天的介绍到此为之,下次我将讲解go的网络库和sync库,来完成go的并法控制和网络编程。