GO语言学习笔记(一) 概述

第一章 概述

该笔记参考 《Go语言学习笔记》

学习go语言之前需要了解的内容:

  1. go语言的编译器将未使用的局部变量定义当作错误来处理
  2. go语言将未使用的导入,当作错误来处理

GO语言的代码文件以.go命名,语句结束分号被默认省略,C样式的注释,入口函数main()没有参数,注意入口函数必须放在main包中。

package main 

func main(){
    println("hello world")
}

1. 基本语句

包导入

import (
    'fmt'
)

流程控制

方式一:

	x := 100
	if x > 0 {
		print(x)
	} else if x == 0 {
		print(x)
	} else {
		print(x)
	}

方式二:

func main() {
	x := 100
	switch {
	case x > 0:
		print("x")
	case x == 0:
		print("0")
	case x < 0:
		print("-x")
	}
}

循环遍历
方式一

func main() {
	for i := 0; i < 5; i++ {
		println(i)
	}

	for i := 4; i >= 0; i-- {
		println(i)
	}
}

方式二

func main() {
	x := 0
	for x < 5 { // 相当于 while(x < 5)
		println(x)
		x++
	}
}
// for 可以当作while来使用
func main() {
	x := 0
	for { // equals to while(True)
		println(x)
		x++
		if x >= 5 {
			break
		}
	}
}

函数

  • 函数可以定义多个返回值,这一点和python很像, 甚至可以对其命名
// div is the function name, and a, b are parameters
// this functions has two returns, one is int type and the other is error type
func div(a, b int) (int, error) {
	if b == 0 {
		return 0, errors.New("division by zero")
	}
	return a / b, nil
}

func main() {
	a, b := 10, 0
	c, err := div(a, b)
	fmt.Println(c, err)
}
  • 函数是第一类型,可以作为参数,或者返回值
// 函数作为返回值
func test(x int) func() {
	return func() {
		println(x)
	}
}

func main() {
	x := 100
	f := test(x)
	f()
}
  • 用defer 定义延迟调用,无论函数是否出错,它都确保结束前被调用
// 用defer 定义延迟调用,无论函数是否出错,它都确保结束前被调用
func test_defer(a, b int) {
	defer println("dispose...") // 通常用来释放资源,解除锁定,或者执行一些清理操作
	// 可以定义多个defer, 按照FIFO顺序执行
	println(a / b)
}

func main() {
	test_defer(10, 5)
}

2. 数据

切片 slice 可以实现类似动态数组的功能

func main() {
	// test_defer(10, 5)
	x := make([]int, 0, 5) // 创建容量为5的切片
	for i := 0; i < 8; i++ {
		x = append(x, i) //追加数据
	}
	fmt.Println(x)
}

map 字典, 将字典类型内置,可以直接从运行时层面获得性能优化

func main() {
	// test_defer(10, 5)
	// x := make([]int, 0, 5) // 创建容量为5的切片
	// for i := 0; i < 8; i++ {
	// 	x = append(x, i) //追加数据
	// }
	// fmt.Println(x)
	m := make(map[string]int) // 创建字典对象
	m["a"] = 1                //  添加或设置
	x, ok := m["b"]           //使用ok-idiom(习惯用语) 获取值,可以知道key/value是否存在
	y, ok := m["a"]
	fmt.Println(x, ok)
	fmt.Println(y, ok)
	delete(m, "a") // 删除字典中key="a"
	z, ok := m["a"]
	fmt.Println(z, ok)
}

结构体 struct 可以匿名嵌入其他类型

type user struct{  // 结构体类型 user 
	name string 
	age byte
}

type manager struct{ // 匿名嵌入其他类型
	user
	title string
}

func main() {
	var m manager
	m.name = "Alice"
	m.age = 29
	m.title = "CTO"
	fmt.Println(m)
}

//  output 
//  {{Alice 29} CTO}

可以为当前包内的任意类型定义方法

type X int

func (x *X) inc() {
	*x++
}

func main() {
	var x X
	x.inc()
	println(x)
}

还可以直接调用匿名字段的方法,这种方式可以实现与继承类似的功能

import (
	"fmt"
)

type user struct {
	name string
	age  byte
}

func (u user) toString() string {
	return fmt.Sprintf("%+v", u)
}

type manager struct {
	user
	title string
}

func main() {
	var m manager
	m.name = "Alice"
	m.age = 29
	println(m.toString()) // 调用 user.toString()方法
}

3. 接口

接口采用了duck type 方式,也就是说无须在实现类型上添加显式声明

import (
	"fmt"
)

type user struct {
	name string
	age  byte
}

func (u user) toString() string {
	return fmt.Sprintf("%+v", u)
}

func (u user) Print() {
	fmt.Printf("%+v\n", u)
}

type Printer interface { // 接口类型
	Print()
}

func main() {
	var m user
	m.name = "Alice"
	m.age = 29
	// 声明一个变量p 类型为Printer,
	//该类型为一个接口类型, 因为m 实现了这个方法
	// 所以 m可以赋值给p
	var p Printer = m
	p.Print()
}

另外,go语言有空接口类型interface{},用途类似OOP里面的system.Object, 可接收任意类型的对象。

4. 并发

整个运行时完全并发化设计,凡是所见的,几乎都在以goroutine方式运行,这是一种比普通协程或线程更加高效的并发设计,能轻松创建和运行成千上万的并发任务。

package main

import (
	"fmt"
	"time"
)

func task(id int) {
	for i := 0; i < 5; i++ {
		fmt.Printf("id = %d: %d\n", id, i)
		time.Sleep(time.Second)
	}
}

func main() {
	go task(1)
	go task(2) // 创建 goroutine

	time.Sleep(time.Second * 6)
}

通道 channel 与 goroutine 搭配,实现用通信代替内存共享的CSP模型

package main

import (
	"fmt"
	"time"
)

func task(id int) {
	for i := 0; i < 5; i++ {
		fmt.Printf("id = %d: %d\n", id, i)
		time.Sleep(time.Second)
	}
}

// 消费者
func consumer(data chan int, done chan bool) {
	for x := range data { // 接收数据
		println("recv:", x)
	}
	done <- true // 通知main, 消费结束
}

// 生产者
func producer(data chan int) {
	for i := 0; i < 4; i++ {
		data <- i // 发送数据
	}
	close(data) // 生产结束,关闭通道
}

func main() {
	done := make(chan bool) // 用于接收消费结束通道
	data := make(chan int)  // 数据管道

	go consumer(data, done) // 启动消费者
	go producer(data)       // 启动生产者

	<-done // 阻塞,直到消费者发回结束信号
}

你可能感兴趣的:(Go语言,学习,golang,开发语言)