最全&最简洁的Go语言入门整理资料 (2)

*接:最全&最简洁的Go语言入门整理资料 (1)

https://blog.csdn.net/qq_42346574/article/details/109232274

三. Go语言基础
2. 流程控制
//if else(分支结构): 主要是括号的位置及省略的表达式的括号;
if 表达式1 {
    分支1
} else if 表达式2 {
    分支2
} else{
    分支3
}
注意:if匹配的左括号必须与if 表达式在同一行,else也必须和上一个if语句的右括号在同一行 且 与else匹配的括号也要在同一行。 
//for (循环结构):
//情况一:
func forDemo() {
	for i := 0; i < 10; i++ {
		fmt.Println(i)
	}
}
//情况二:
func forDemo2() {
	i := 0
	for ; i < 10; i++ {
		fmt.Println(i)
	}
}
//情况三:(初始语句和结束语句都可以省略,类似于while)
func forDemo3() {
	i := 0
	for i < 10 {
		fmt.Println(i)
		i++
	}
}
//无限循环:
for {
    循环体语句
} 
//在Go中没有其它语言中例如while这类的循环关键词,通常是使用for来代替。

for range(键值循环):
针对不同类型数据返回值不同:

  1. 数组、切片、字符串返回索引和值。
  2. map返回键和值。
  3. 通道(channel)只返回通道内的值。
//switch语句:
switch case:
例如: switch A:=3; A {
       case 1:
           语句
           fallthrough /*fallthrough 语法可以执行满足条件的case的下一个case,即case2的语句。通常是用来简化判断语句 */
       case 2:
       default:
       }  
//总的来说这个用法与其他语言比较类似。
goto(跳转到指定标签)
比如:条件判断满足的时候
	goto breaktag
breaktag:
    fmt.Println("结束for循环") //这样子可以快速跳出多层循环
//这样可以快速跳出循环,在多层循环中可以减少条件判断语句,快速跳出循环。
breakcontinue的用法与C语言一样。
3. 数组、切片、map数据类型
  • 数组相关知识:
//数组array:
// 定义一个长度为3元素类型为int的数组a --> var a [3]int
初始化方法:
方法1var a [3]int //自动初始化为int类型的0值
var numArray = [3]int{1, 2}  
var cityArray = [3]string{"北京", "上海", "深圳"}
方法2var numArray = [...]int{1, 2}
var cityArray = [...]string{"北京", "上海", "深圳"}
方法3:
a := [...]int{1: 1, 3: 5} //1:1表示索引从0到1,第二位是1,3:5是第四位是5。
数组遍历:
for i := 0; i<len(a); i++ {
}//或者
for index, value := range a {
}
Go语言是支持多维数组的,用法都比较类似。注意多维数组只有第一层可以使用...来让编译器推导数组长度。
  • 切片的相关知识:
//切片slice:
切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。
定义:var name []T
-->go语言中nil是一个经常使用的,重要的预先定义好的标识符。它是许多中类型的零值表示。
可以使用make()函数构造切片:make([]T, size, cap) //T元素类型、size切片元素数量、cap切片的容量
    a := make([]int, 2, 10) 
判断切片是否为空:
请始终使用len(s) == 0来判断,而不应该使用s == nil来判断。

在这里插入图片描述
在这里插入图片描述

  1. 切片的复制拷贝:

    func main() {
    	s1 := make([]int, 3) //[0 0 0]
    	s2 := s1             //将s1直接赋值给s2,s1和s2共用一个底层数组
    	s2[0] = 100
    	fmt.Println(s1) //[100 0 0]
    	fmt.Println(s2) //[100 0 0]
    }
    
  2. 切片的遍历与数组一致,有索引遍历和for range遍历;

  3. append( )方法为切片添加元素:

    var s []int //不用进行初始化,可以直接使用append()函数。
    s = append(s, 1)        // [1]
    s = append(s, 2, 3, 4)  // [1 2 3 4]
    s2 := []int{5, 6, 7}  
    s = append(s, s2...)    // [1 2 3 4 5 6 7] 往s中添加另外一个切片的元素后边要加上...(三个点)
    
  4. 切片类型是引用类型,所以在 b := a直接赋值的时候,指向的是同一块内存地址。
    使用copy函数复制切片:
    copy(destSlice, srcSlice []T)
    例如:

    a := [ ]int {1, 3, 5, 7, 9}
    c := make([ ]int, 5, 5)
    copy(c, a)//这不是同一块内存空间,所以修改的时候是会有区别的。

  5. 从切片中删除元素:

    Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。比如直接:a = append(a[ :2 ], a[ 3: ]…)这样就把第三个值删除了。

  • map数据相关知识:

map数据类型:
1.map定义为map[KeyType] ValueType
2.也可以使用make()来分配内存,语法为
make(map[KeyType]ValueType, [cap])
3.判断某个键是否存在?
scoremap := make(map[string]int)
scoremap[“Hao”] = 100
socremap[“Leo”] = 60
v, ok := scoremap[“Hao”]
if ok {
fmt.Println(v)
} else {
fmt.Println(“查无此人!”)
}
4.map遍历:
for k, v := range map {
fmt.Println(k, v)
}//只想遍历key的时候
for k := range map {
fmt.Println(k)
}
注意: 遍历map时的元素顺序与添加键值对的顺序无关。
5.map中删除键值对
delete(map, key) 例如 delete(scoremap, “张三”)
6.按照指定的顺序遍历map
申请切片空间–>将map中的key值存到切片空间中–>对该切片进行排序–>最后按照排序后的key遍历map
7.切片类型map
slicemap := make(map[string][ ]string, 3)
key := “中国”
k, ok := slicemap[key]
if !ok {
value = make([]string, 0, 2)
}
value = append(value, “BJ”, “SH”)
slicemap[key] = value

4. 函数
函数定义:
    func 函数名(参数)(返回值){
        函数体
    }
参数:
    1.类型简写成 (x,y int)
    2.可变参数:(x... int) //x是一个切片类型 可变参数是通过切片来实现的。
返回值:
    3.多返回值用()包裹起来,(int, int) 需要返回return sum, sub
    或者是直接在函数定义的时候直接给返回值命名,(sum, sub int) 则返回的时候直接return
    再或者返回的东西是空的切片之类的,则可以用nil来代替;
变量的作用域:
    4.全局变量:定义在函数外 var n int = 100
    5.局部变量:函数内定义的无法在函数外使用,如果局部变量和全局变量重名时,优先访问局部变量。
函数类型与变量:
    type可以来定义一个函数类型,calculation类型就是一种函数类型,这种函数接收两个int参数并且返回一个int类型的返回值。
    比如:func add(x, y int) int {
	          return x + y
          }
          var c caculation
          c = add //然后c就可以跟add一样调用 c(2, 4)
高阶函数:分为函数作为参数和函数作为返回值两部分。
    1.作为参数如下:
    func add (x, y int) int{
        return x + y
    }   
    func sub (x, y int) int{
        return x - y
    }
    func calcu(x, y int, op func (int, int) int) int {
        return op(x, y)
    }
    func main() {
        ret2 := calcu(10, 20, add)
        fmt.Println(ret2) //30
    }
    2.作为返回值:
    func do(s string) (func(int, int) int, error) {
    	switch s {
    	case "+":
    		return add, nil
    	case "-":
    		return sub, nil
    	default:
    		err := errors.New("无法识别的操作符")
    		return nil, err
	}
}
匿名函数和闭包:
    1.匿名函数:
        是没有函数名的函数,函数作为返回值因此在函数内部就不能像之前那样定义函数了。由于没有函数名所以它不能像普通函数那样调用,所以匿名函数需要保存到某个变量或作为立即执行数;
        // 将匿名函数保存到变量
    	add := func(x, y int) {
    		fmt.Println(x + y)
    	}
    	add(10, 20) // 通过变量调用匿名函数
    
    	//自执行函数:匿名函数定义完加()直接执行
    	func(x, y int) {
    		fmt.Println(x + y)
    	}(10, 20)
        匿名函数多用于实现回调函数和闭包。
    2.闭包:
        闭包指的是一个<函数> + <引用环境>组合而成的实体。
        func add(x int) func(int) int {
            return func (y int) int {
                x += y
                return x
            }
        }
        func mian() {
            var f = add(10) //在f的生命周期中变量x一直有效此时的f就是一个闭包
            fmt.Println(f(10)) //20
            fmt.Println(f(20)) //40
            var f1 = add(20)
            fmt.Println(f1(20))//40
        }
        两个函数的情况:
        func calcu(base int) (func(int) int, func(int) int) {
            add := func(i int) int {
                base += i
                return base
            }
            sub := func(i int) int {
                base -= i
                return base
            }
            return add, sub
        }
        func main() {
            f1, f2 := calcu(10)
            fmt.Println(f1(1), f2(2))//11, 9
            fmt.Println(f1(3), f2(4))//12, 8
        }
defer语句:
    defer语句是会将后边跟随的语句进行延迟处理,在defer归属的函数即将返回执行的时候,则将延迟的所有语句按照defer定义的逆序进行执行。
    defer经典案例:这个搞懂稍微比较复杂,需要自行去查阅相关的资料,我目前也没弄得十分明白/(ㄒoㄒ)/~~
        func f1() int {
        	x := 5
        	defer func() {
        		x++
        	}()
        	return x
        }

        func f2() (x int) {
        	defer func() {
        		x++
        	}()
        	return 5
        }
        
        func f3() (y int) {
        	x := 5
        	defer func() {
        		x++
        	}()
        	return x
        }
        func f4() (x int) {
        	defer func(x int) {
        		x++
        	}(x)
        	return 5
        }
        func main() {
        	fmt.Println(f1()) //5
        	fmt.Println(f2()) //6
        	fmt.Println(f3()) //5
        	fmt.Println(f4()) //5
        }
内置函数:
    close	主要用来关闭channel
    len	    用来求长度,比如string、array、slice、map、channel
    new	    用来分配内存,主要用来分配值类型,比如intstruct。返回的是指针
    make	用来分配内存,主要用来分配引用类型,比如chanmap、slice
    append	用来追加元素到数组、slice中
    panicrecover	用来做错误处理
panic/recover函数:
    Go语言中目前(Go1.12)是没有异常机制,但是使用panic/recover模式来处理错误。
    panic可以在任何地方引发,但recover只有在defer调用的函数中有效。见下边的例子: 
    func funcB() {
    	defer func() {
    		err := recover()
    		//如果程序出出现了panic错误,可以通过recover恢复过来
    		if err != nil {
    			fmt.Println("recover in B")
    		}
    	}()
    	panic("panic in B")
    }
    注:1.recover()必须搭配defer使用。
        2.defer一定要在可能引发panic的语句之前定义。

之后我将会继续更新Go语言中的指针、结构体之类知识,开始面向对象的思想啦!还有有关Go语言中的包、接口、反射,以及它最重要的特性:并发概念等的学习笔记。欢迎大家继续关注!谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郝同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值