Go基础-3

1. 内置运算符

1.1 算数运算符.

运算符 含义
+ 相加
- 相减
* 相乘
/ 相除
% 取余
i++ i=i+1

1.2 关系运算符

运算符 含义
== 是否相等
!= 是否不相等
> 是否大于
>= 是否大于等于
< 是否小于
<= 是否小于等于

1.3 赋值运算符

运算符 含义
= 赋值
+= 相加后赋值
-= 相减后赋值
*= 相乘后赋值
/= 相除后赋值
%= 取余后赋值

1.4 逻辑运算符

运算符 含义
&& 逻辑AND
|| 逻辑OR
! 逻辑NOT

2. 条件循环

2.1 if else分支

	// 1. if else
	if score := 1; score > 90 {
    
    
		fmt.Print("真优秀")
	} else if score >= 60 {
    
    
		fmt.Print("太棒了,过关了")
	} else {
    
    
		fmt.Print("没及格请加油")
	}
	结果
	没及格请加油

2.2 for循环

	for i := 1; i <= 100; i++ {
    
    
		fmt.Println(i)
	}

2.3 for模拟while循环

	k := 1
	for {
    
    
		if k <= 10 {
    
    
			fmt.Println(k)
		} else {
    
    
			break
		}
		k++
	}

2.4 for range

	s := "hello world"
	for _, val := range s {
    
    
		fmt.Printf("%c", val)
	}
	结果
	hello world

2.5 switch case

可以解决大量的if else的情况

	score := "C"
	switch score {
    
    
	case "A":
		fmt.Println("非常棒!")
	case "B":
		fmt.Println("你很棒")
	case "C":
		fmt.Println("及格啦")
	default:		//如果都不成立则走default
		fmt.Println("下次加油!")
	}
	结果
	及格啦

2.6 break continue

2.6.1 break

	for i := 0; i < 10; i++ {
    
    
		if i == 5 {
    
    
			break
		}
		fmt.Println(i)
	}
	结果
	0
	1
	2
	3
	4

2.6.2 continue

	for i := 0; i < 10; i++ {
    
    
		if i == 5 {
    
    
			//break
			continue
		}
		fmt.Println(i)
	}
	结果
	输出0-9但没5

3. 函数

3.1 函数定义和返回值

  • 函数是组织好的,可以重复使用的,用于执行指定任务的代码块

func是go25个关键字中的一个

func sum(x, y int) int {
    
    
	return x + y
}

func main() {
    
    
	x := sum(5, 6)
	fmt.Println(x)
}
结果
11

4. 作用域

  1. 执行定义全局变量(函数外部定义),可以在其他函数中直接使用

    var num int = 64
    func main() {
          
          
    	fmt.Println(num)
    	....
    }
    
  2. init方法

  3. main方法

局部作用域优先级更高,局部和全局定义了相同的变量名,局部在函数内生效,全局被覆盖.

var num int = 64

func init() {
    
    
	num += 1
}
func main() {
    
    
	fmt.Println(num)
	for num := 0; num < 10; num++ {
    
    
		fmt.Println(num)
	}
	fmt.Println(num)
}
结果
65
0
1
2
3
4
5
6
7
8
9
65

5. 结构体

GO语言中没有类的概念,也不支持类的继承和面向对象的概念.

Go语言中通过结构体的内嵌再配合接口比面向对象更具有高扩展性和灵活性.

5.1 定义结构体

func main() {
    
    
	var p1 Person
	p1.Age = 28
	p1.Name = "zhangsan"
	fmt.Println(p1)
	fmt.Println(p1.Name)

}

// type : 关键字
// Person : 结构体的名字
// struct: 定义结构体的关键字
type Person struct {
    
    
	Name string
	Age  int
}

键值对初始化

func main() {
    
    
	p3 := Person{
    
    
		Name: "张飞",
		Age:  33,
	}
	fmt.Println(p3)
}

// type : 关键字
// Person : 结构体的名字
// struct: 定义结构体的关键字
type Person struct {
    
    
	Name string
	Age  int
}

5.2 结构体方法和接收者

所谓的方法就是定义了接收者的函数.

  • Go语言中的方法(Method)是一种作用于特定类型变量的函数.
  • 这种特定类型变量叫做接受者
  • 接收者的概念就类似于其他语言中的this或者self.
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
    
    
	函数体
}

(p Person): 接收者

p类似于python中的self或者js中的this

Person 接收者的结构体

printInfo():一个方法绑定了结构体之后,就叫做结构体方法

type Person1 struct {
    
    
	Name string
	Age  int
}
func (p Person1) printInfo() {
    
    
	fmt.Println(p.Name, p.Age)
}

通过类调用方法

结构体的方法:用来模拟其他语言中的类

  1. 定义结构体
  2. 实例化结构体
  3. 结构体绑定方法和接收者
  4. 调用结构的方法
func main() {
    
    
	p := Person1{
    
    
		Name: "张三",
		Age:  23,
	}
	p.printInfo()
}

type Person1 struct {
    
    
	Name string
	Age  int
}

func (p Person1) printInfo() {
    
    
	fmt.Println("name:", p.Name, p.Age)
}
结果
name: 张三 23

5.3 值类型和指针类型接收者

  1. 值类型的接收者

    1. 当方法作用于值类型接收者时,将接收者的值复制一份
    2. 在值类型接收者的方法中可以获取接收者的成员值,但 修改操作知识针对副本,无法修改接收者变量本身
  2. 指针类型的接收者

    1. 指针类型的接收者由一个结构体的指针组成
    2. 调用方法时,修改接收者指针的任意成员变量,在方法结束后,修改都是有效的.
    3. 这种方式十分接近其他语言中面向对象中的this或者self

5.3.1 值接收者

只传递了拷贝的一份数据,值修改了数据只修改了拷贝的数据,原来的数据不修改

// 1.定义结构体
type test struct {
    
    
	name string
	age  int
}

// 3.绑定方法
func (p test) GetInfo() {
    
    
	fmt.Println(p.name, p.age)
	p.name = "lisi"
}

func main() {
    
    
	//2. 实例化结构体
	p := test{
    
    
		name: "zhangsan",
		age:  23,
	}
	p.GetInfo()
	fmt.Println(p.name)
}
结果
zhangsan 23
zhangsan

5.3.2 指针接收者

指针类似于python的self

// 1.定义结构体
type test struct {
    
    
	name string
	age  int
}

// 3.绑定方法
func (p *test) GetInfo() {
    
    		//区别在这一行
	fmt.Println(p.name, p.age)
	p.name = "lisi"
}

func main() {
    
    
	//2. 实例化结构体
	p := test{
    
    
		name: "zhangsan",
		age:  23,
	}
	p.GetInfo()
	fmt.Println(p.name)
}
结果
zhangsan 23
lisi

5.4 struct和sting转换

json.Marshal返回两个值.

第一个值: sByte 是一个[]byte的对象.就是结构体转换后的数据

第二个值: err 如果json.Marshal转换失败,则会将错误抛给err

string(sByte)就是将[]byte类型转换为string类型

func main() {
    
    
	// 2. 初始化结构体
	s := Student{
    
    
		ID:      1,
		Name:    "ZHANGSAN",
		Age:     23,
		Address: "bj",
	}
	fmt.Printf("%T %#v\n", s, s)
	// 3. 将结构体转json
	sByte, err := json.Marshal(s)
	if err != nil {
    
    
		fmt.Println("json.Marshal err, ", err)
	}
	fmt.Println(string(sByte))
}

// 1. 定义结构体
type Student struct {
    
    
	ID      int
	Name    string
	Age     int
	Address string
}
结果
main.Student main.Student{
    
    ID:1, Name:"ZHANGSAN", Age:23, Address:"bj"}
{
    
    "ID":1,"Name":"ZHANGSAN","Age":23,"Address":"bj"}

5.5 string 转json

// sting to json
func main() {
    
    
	s := School{
    
    
		Name:    "China",
		City:    "Beijing",
		Country: "China",
		Age:     18,
	}
	b, _ := json.Marshal(s)
	println(string(b))
	// 结构体对应的json字符串数据
	// 将json字符串转换为struct结构体
	var stu School
	// 将struct类型转换为byte类型.
	json.Unmarshal(b, &stu)
	fmt.Printf("%T %#v", stu, stu)
}

type School struct {
    
    
	Name    string
	Age     int
	City    string
	Country string
}
结果
{
    
    "Name":"China","Age":18,"City":"Beijing","Country":"China"}
main.School main.School{
    
    Name:"China", Age:18, City:"Beijing", Country:"China"}

5.6 结构体嵌套

func main() {
    
    
	p := Person{
    
    
		Name: "John",
		Age:  20,
		Cls: []Class{
    
    
			{
    
    
				Age:     20,
				City:    "上海",
				Country: "中国",
			},
			{
    
    Age: 23, City: "北京", Country: "中国"},
			{
    
    Age: 43, City: "纽约", Country: "美国"},
		},
	}
	s, err := json.Marshal(p)
	if err != nil {
    
    
		panic(err)
	}
	fmt.Println(string(s))
}

type Person struct {
    
    
	Name string
	Age  int
	Cls  []Class
}

type Class struct {
    
    
	Age     int
	City    string
	Country string
}
结果
{
    
    "Name":"John","Age":20,"Cls":[{
    
    "Age":20,"City":"上海","Country":"中国"},{
    
    "Age":23,"City":"北京","Country":"中国"},{
    
    "Age":43,"City"
:"纽约","Country":"美国"}]}

5.7 Struct Tag

  1. Tag标签说明

    Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来

    Tag在结构体字段的后方定义,由一对反引号来包裹

    结构体Tag由一个或多个键值对组成,键与值使用冒号分隔,值使用双引号括起来

    同一个结构体字段可以设置多个键值对tag,不同键值对之间使用空格分割.

func main() {
    
    
	s1 := Config{
    
    
		Name: "张三",
		Age:  18,
	}
	s, _ := json.Marshal(s1)
	fmt.Print(string(s))
}

type Config struct {
    
    
	Name string `json:"name"`
	Age  int    `json:"age"`
}
结果:
{
    
    "name":"张三","age":18}

6. 面向对象

6.1 Golang接口定义

在go语言中接口(interface)是一种类型,一种抽象的类型

接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节

func main() {
    
    
	c := Cat{
    
    name: "小猫"}
	fmt.Println(c.Say())
	d := Dog{
    
    name: "阿黄"}
	fmt.Println(d.Say())
}

type Cat struct {
    
    
	name string
}
type Dog struct {
    
    
	name string
}

func (c Cat) Say() string {
    
    
	return c.name + ":喵喵喵"
}
func (d Dog) Say() string {
    
    
	return d.name + ":汪汪汪"
}
结果:
小猫:喵喵喵
阿黄:汪汪汪 
func main() {
    
    
	p := Computer{
    
    
		Name: "Lenovo",
	}
	var p1 Inter
	p1 = p
	p1.Start()
	p1.Stop()
	p1.Reboot()
}

type Inter interface {
    
    
	Start()
	Stop()
	Reboot()
}
type Computer struct {
    
    
	Name string
}

func (c Computer) Start() {
    
    
	fmt.Printf("%s 开机中....\n", c.Name)
}
func (c Computer) Stop() {
    
    
	fmt.Printf("%s 关机中....\n", c.Name)
}
func (c Computer) Reboot() {
    
    
	fmt.Printf("%s 重启中....\n", c.Name)
}
结果
Lenovo 开机中....
Lenovo 关机中....
Lenovo 重启中....

7. 空接口null_interface

Golang中的空接口可以不定义任何方法,没有定义任何方法的接口就是空接口.(泛型概念)

空接口表示没有任何约束,因此任何类型变量都可以实现空接口

空接口在实际项目中是非常多的,用空接口可以表示任意数据类型.

  1. 空接口作为函数的参数
func main() {
    
    
	Show(1)
	Show("aa")
}

func Show(val interface{
    
    }) {
    
    
	fmt.Printf("%v\n", val)
}
结果:
1 
aa
  1. 切片定义空接口
	s1 := []interface{
    
    }{
    
    1, 2, 3, "12aa"}
	fmt.Println(s1)
	结果
	[1 2 3 12aa]
  1. 定义map的空接口
	d := map[string]interface{
    
    }{
    
    
		"name": "aa",
		"age":  12,
	}
	fmt.Println(d)
  1. 断言定义

    断言一般返回两个值,一个是变量本身的值,另一个是是当前类型

	var x interface{
    
    }
	x = 1
	v, ok := x.(int)
	fmt.Println(v, ok)
	结果:
	1 true

8. 值接收者和指针接收者

8.1 值接收者

当方法用于值类型接收者时,Go语言会在代码运行时将接收者的值复制一份.

在值类型接收者的方法中可以获取接收者的成员值,但修改操作只是针对副本,无法修改接收者变量本身.

8.2 指针接收者

指针类型的接收者由一个结构体的指针组成

由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改都是有效的.

这种方式十分接近于其他语言中面向对象中的this或者self.

8.3 指针类型使用时机

  1. 需要修改接收者中的值
  2. 接收者是拷贝代价比较大的大对象
  3. 保证一致性,如果某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者.

总结:

如果接口中使用的是指针类型作为接收者,那么只能使用指针类型的结构体进行调用.不能使用值类型的结构体调用.

指针对象一旦一个地方修改,其他地方也跟着修改.(只存了一份数据)

值对象由于是拷贝数据,所以修改一处数据,其他数据不受影响.

猜你喜欢

转载自blog.csdn.net/qq_29974229/article/details/128196362