当前位置: 首页 > 科技观察

Go学习:那些不同的知识点(下)

时间:2023-03-14 15:57:03 科技观察

在学习Go语言的过程中,会涉及到语法,数据结构,以及一些Go特有的东西,其中有很多现在还印象深刻。这篇文章会说说Go语言的差异。1.变量和函数的声明packagemainimport"fmt"funcmain(){varnamestringname="oec2003"age:=18fmt.Println(name,age)}上面的例子是变量的声明方式,可以看下面C#中的区别是类型写在变量名后面,而Go中的函数也遵循这个原则:funcgetName(namestring)string{return"hello,"+name}函数的定义使用func关键字。参数类型也写在参数名称之后。函数的返回值写在方法名后面。2、不支持类型的隐式转换为了提高代码的可读性,避免一些隐藏的错误,Go不支持类型的隐式转换。在C#中,如下代码可以正常编译运行:staticvoidMain(string[]args){inta=18;长b=a;Console.WriteLine(b);}但在Go中,以下代码会出现编译错误:funcmain(){varaint16=10varbint32=afmt.Println(b)}int16和int16之间没有隐式转换int32,只能显式转换,如下:funcmain(){varaint16=10varbint32=int32(a)fmt.Println(b)}3.运算符为了提高生产率,避免语言错误,Go非常严格,不支持前缀++和--:funcmain(){a:=10a++//可以支持post++和--++a//不支持pre++和--}的数组的比较也和C#不同,比如在C#中比较两个长度相同,值相同的数组返回False:staticvoidMain(string[]args){int[]a=new[]{1,2,3};int[]b=new[]{1,2,3};控制台.WriteLine(a==b);但是在Go中它会有不同的结果:funcmain(){a:=[...]int{1,2,3,4}b:=[...]int{1,2,3,4}fmt.Println(a==b)b=[...]int{1,2,3,5}fmt.Println(a==b)b=[...]int{1,2,4,3}fmt.Println(a==b)}4.map的值可以是函数map在Go和C#Dictionary有点像,map的值可以是普通数据类型,也可以是函数:packagemainimport("fmt")funcaa(numint)int{returnnum*num}funcmain(){m:=map[int]func(aint,bint)int{}m[1]=func(aint,bint)int{returna+b}m[2]=func(aint,bint)int{returna-b}m[3]=func(aint,bint)int{returna*b}m[4]=func(aint,bint)int{returna*b}m[1](12,3)for_,f:=rangem{fmt.Println(f(12,3))}}15936365.条件判断Go中的条件判断也有两种,if和switch。if可以支持条件表达式中的变量赋值:funcmain(){m:=map[int]string{1:"oec2003",2:"fengwei"}ifv,isExist:=m[2];isExist{fmt.Println(v)}else{fmt.Println("doesnotexist")}}if后面的表达式分为两段。第一节给变量赋值;第二段进行条件判断,两段之间用分号隔开。第二段的条件判断必须返回一个布尔值。switch的使用也有些不同:单个case可以支持多个值,用逗号隔开。无需显式添加中断即可退出案例。switch之后不能有表达式,就好像if一样。funcmain(){switchos:=runtime.GOOS;os{case"darwin":fmt.Println("systemismac")case"linux":fmt.Println("systemislinux")default:fmt.Println("Others")}}name:="oec2003"switch{casename=="oec2003":fmt.Println("nameisoec2003")default:fmt.Println("nameisundefine")}name:="fengwei"switchname{case"oec2003","fengwei":fmt.Println("It'sallmyname")default:fmt.Println("Idon'tknow")}6.Loop在Go语言中,关键字很少,因此循环处理只有一个关键字for。n:=0forn<5{fmt.Println(n)n++}for{fmt.Println("这是一个无限循环")}fori:=0;我<10;i++{fmt.Println(i)}a:=[...]int{1,2,3,4}forv:=rangea{fmt.Println(v)}上面用关键字包含了所有遍历C#中的方法。for后面的表达式不需要写括号。7、特殊的main函数一个简单完整的Go程序如下:和参数,如果需要在main函数中使用参数,需要引入os包:packagemainimport("fmt""os")funcmain(){iflen(os.Args)>1{fmt.Println("hello",os.Args[1])}for_,arg:=rangeos.Args{fmt.Println(arg)}}os.Args是一个字符串数组。使用范围可用于遍历数组。使用_infor省略第一个参数。8、初始化函数我们知道,在Go语言中,main函数是程序的入口函数,但main函数并不是最先执行的函数。在main之前,有一个init函数会先被执行。在init函数中,可以做一些初始化工作:packagemainimport("fmt")funcinit(){fmt.Println("Initializationworkhere")}funcmain(){fmt.Println("程序开始执行")}9.支持多个函数返回值C#中一个函数支持多个返回值的方式有很多种,例如:返回一个对象,使用out作为参数,C#7.0新增的函数tuple,下面是C#Value中返回多个值的方式:classProgram{staticvoidMain(string[]args){varuserInfo=GetUserInfo();varname=userInfo.name;varage=userInfo.age;Console.WriteLine(姓名+年龄);}static(stringname,intage)GetUserInfo(){return("oec2003",18);}}Go语言的函数返回多个值和C#元组的方式类似:packagemainimport("fmt")funcgetUserInfo()(string,int){return"oec2003",18}funcmain(){name,age:=getUserInfo()fmt.Println(name,age)}接收值时,如果有些值不需要,可以用_忽略:funcgetUserInfo()(string,int){return"oec2003",18}funcmain(){name,_:=getUserInfo()fmt.Println(name)}10.函数的延迟执行在Go中,使用defer关键字让函数延迟执行,可以用来释放资源,释放锁等,先看下面代码,一清二楚defer关键字加在函数前面。虽然是main函数的第一行,但是最后会调用:fmt.Println("ProgramStart")}程序开始清理资源。使用panic使程序崩溃。你会发现defer定义的函数在最后还是会执行:packagemainimport("fmt")funcclear(){println("清理资源")}funcmain(){deferclear()fmt.Println("Programstarts")panic("Programcrashes")}Programstartstocleanupresourcespanic:Programcrashes这个有点像在C#中使用trycatch,异常被捕获后,finally块中的代码仍然会被执行。我觉得Go语言的这种处理方式更加灵活,以组合的方式达到目的,也符合Go语言的设计理念