本文已参与「新人创作礼」活动,一起开启掘金创作之路。
到了这一个环节,整个Go的基础入门就告一段落了,了解了Go的基本数据类型和相关语法,后面就是基础篇了
Go语言的接口
//无参数的接口实现
package main
import "fmt"
type Phone interface {
call()
}
type NokiaPhone struct {
//
}
func (np NokiaPhone) call() {
fmt.Println("I am Nokia, I can call your family")
}
type Iphone struct {
//
}
func (ip Iphone) call() {
fmt.Println("I am Iphone, I can eat Japan")
}
func main() {
/*
接口:把所有具有共性的方法定义在一起,任何其他类型只要
实现了这些方法就是实现了这个接口
*/
var p Phone
p = new(NokiaPhone)
p.call()
p = new(Iphone)
p.call()
}
//带参数的接口实现
package main
import "fmt"
type Animal interface {
eat()
}
type Cat struct {
name string
}
func (cat Cat) eat() {
fmt.Println(cat.name + "猫吃东西")
}
type Dog struct{}
func (dog Dog) eat() {
fmt.Println("狗吃东西")
}
func main() {
var animal1 Animal = Cat{"Tom"}
var animal2 Animal = Dog{}
animal1.eat()
animal2.eat()
}
Go语言的错误处理
package main
import "fmt"
/*
1、panic 在没有用 recover 前以及在 recover 捕获那一级函数栈,panic 之后的代码均不会执行;一旦被 recover 捕获后,外层的函数栈代码恢复正常,所有代码均会得到执行;
2、panic 后,不再执行后面的代码,立即按照逆序执行 defer,并逐级往外层函数栈扩散;defer 就类似 finally;
3、利用 recover 捕获 panic 时,defer 需要再 panic 之前声明,否则由于 panic 之后的代码得不到执行,因此也无法 recover;
*/
//实现
func main() {
fmt.Println("外层开始")
defer func() {
fmt.Println("外层准备recove")
if err := recover(); err != nil {
//err已在上一级函数中被捕获,这里没有异常
fmt.Printf("%#v-%#v\n", "外层", err)
} else {
fmt.Println("外层啥也没做")
}
fmt.Println("外层完成recover")
}()
fmt.Println("外层即将异常")
fff()
fmt.Println("外层异常后")
defer func() {
fmt.Println("外层异常后defer")
}()
}
func fff() {
fmt.Println("内层开始")
defer func() {
fmt.Println("内层recover前的defer")
}()
defer func() {
fmt.Println("内层准备recover")
if err := recover(); err != nil {
// err 是 panic传入的内容
fmt.Printf("%#v-%#v\n", "内层", err)
}
fmt.Println("内层完成recover")
}()
panic("异常信息")
defer func() {
fmt.Println("内层异常后的defer")
}()
//recover捕获的一级或者完全不捕获,这里开始下面的代码不会再执行
fmt.Println("内层异常后语句")
}
Go语言的并发
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
/*
Go语言支持并发,我们只需要通过go关键字来开启goroutine就行
goroutine是轻量级线程,goroutine的调度是由Golang运行时进行管理的
*/
go say("world")
say("hello")
//输出的hello和world没有固定的先后顺序,因为它们在两个goroutine上执行
}
/*
通道(channel)是用来传递数据的一个数据结构
通道可用于两个goroutine之间通过传递一个指定类型的值来同步运行和通讯
操作符<-用于指定通道的方向,发送或接收
若没有指定方向,则为双向通道
*/
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum //把sum发送到通道c
}
func main() {
s := []int{7, 2, 8, -7, 1, 0}
c := make(chan int)
go sum(s[:len(s)/2], c) //从 0 到 len/2 的元素值相加
go sum(s[len(s)/2:], c) //从 len/2 到 最后的元素值相加
x, y := <-c, <-c //从通道c中接收
fmt.Println(x, y, x+y)
go sum(s[:len(s)/2], c) //给上述注释给出证明
z := <-c
fmt.Println(z)
}
/*
通道缓冲区
*/
package main
import "fmt"
func main() {
//定义一个可以存储整数类型的带缓冲通道
ch := make(chan int, 2) //缓冲区大小为2
//带缓冲通道可以同时发送两个数据,而不用立刻去同步读取数据
ch <- 'a'
ch <- 2
//获取这两个数据
fmt.Println(<-ch)
fmt.Println(<-ch)
}
package main
import "fmt"
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
/*
range 函数遍历每个从通道接收到的数据,通道c在发送完10个数据后就把通道关闭了
所以我们在接收第11个数据的时候就阻塞了
*/
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
Go语言的使用工具
我使用的工具是Goland,一个IDE,非常好用,就是有点贵,可以去淘宝上买激活码,或者去百度上搜方法,建议直接淘宝解决,反正就一丢丢钱,时间可是很宝贵的,别浪费太多时间在工具上。也有其他好用的工具,但我更喜欢这个IDE,更方便。