Go语言自学笔记(一)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_18800771/article/details/96642743

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

Go语言的基本语句:

package main    //声明main包
import "fmt"    //导入fmt包
func main(){    //创建主函数
	fmt.Println("Hello go")    //调用fmt包中的打印函数
}

需要注意的是:

Go程序是通过package来组织的,区别于java语言程序以类来组织程序。同时,每个文件必须先声明包,程序必须有一个package main,只有package 名称为main的包可以包含main函数,一个可执行程序有且仅有一个main包 ,即Go语言程序中存在且仅存在一个入口函数main函数,类似于java语言程序公共类里面的main方法。其中,Go语言对于函数的左大括号‘{’具有严格的要求:{不可以独占新行,相应代码末尾也无需添加分号。

func main(){
}

在主函数中调用其他函数时,大部分的函数都需要导入包,才能完成相应的功能。但不同于其他语言,在Go语言的程序中,如果使用import导入包之后,一定要使用包内函数,否则就会报错。同理,若在程序中声明了量,那也必须要使用,否则就会报错,这也是Go语言比较不人性化的一点。

import “fmt”

存在于“fmt”当中的Println()函数则是能够自动换行的打印函数。

fmt.Println("Hello go")

Go语言注释方式与其他语言相似:

//为单行注释

/*

这样的注释块可一次性注释多行

*/

关于Go语言程序的运行:

Go语言中大部分的编译代码都在命令指令行中输入,例如:

我们使用Liteide时,一个Go工程之中只能有一个main函数,此时的解决方法有二:

1.一个Go工程会在一个文件夹之中,我们可以将新程序放入另一个文件夹中,但此方法较为繁琐。

2..我们可以再命令指令行中执行文件:

通过go build name.go可以编译name.go文件中的代码,生成一个name.exe可执行文件,运行可执行文件。

我们也可以通过go run name.go在不生成明显程序的情况下直接编译运行(推荐)。

Go语言中的基本数据类型:

为方便管理并且分配内存空间需明确数据类型:

为Go语言中的量命名时有一定的规范:
1.量的名称只由字母,下划线,数字组成
2.量的名称不能以数字开头
3.量的名称不能与Go语言相关关键字重名
4.量在命名时需区分大小写

Go语言中的关键字有25个,只能在特定结构中使用:

此外还有大约30多个预定义名字:


 Go语言中的量-以整型为例:

变量:顾名思义,就是在程序运行期间可以改变的量,我们可以通过以下语法来声明变量:

变量的声明:

格式:关键字(var)  变量名称   数据类型

var name int    //用来定义一个整型变量name
var name0, name1 int    //用来定义两个个整型变量name0与name1

要注意:

声明但没有初始化的整型变量会被默认赋初始值0。

同一个大括号里面的变量名是唯一的,不可以同名,也不可以重复定义。

变量的赋值:为变量赋值前必须先声明变量,变量可以多次被赋值以达到修改变量的值得目的。若在程序中声明了量,那也必须要使用,否则就会报错。

name=20    //将变量name的值赋为20
name0,name1 = 30,40    //将变量name0,name1分别赋值为30,40

显然,在定义变量之后再为变量赋值有些繁琐,我们可以通过其他的方式在定义的同时为变量初始化,声明并初始化的过程等同于先声明变量再为变量赋值。

var name int = 10    //初始化变量name
var name0, name1 int = 30, 40    //用来定义两个整型变量name0与name1

同时,我们也可以使用变量的自动推导类型:必须初始化,通过初始化的值来确定数据类型。此方法较为常用并且较为简便,等同于先声明后赋值,同样不可以同名,不可以重复定义。

name:=10    //自动推导类型赋值
name0, name1 := 30, 40    //自动推导类型赋值,多重赋值
var name2 = 50

这时有必要提及Go语言中对两个变量值的互换上的代码优化:

我们使用的传统方法:

package main
import "fmt"
func main(){
	var num0, num1 int = 10,20
	var tmp int
	fmt.Println(num0,num1,tmp)
	//开始交换num0,num1的值
	tmp=num0
	num0=num1
	num1=tmp
	fmt.Println(num0,num1,tmp)
}

在Go语言中,通过自动推导类型,我们这可以写出如下等效代码:

package main
import "fmt"
func main(){
	num0, num1 := 10, 20
	fmt.Println(num0,num1)
	//开始交换num0,num1的值
	num0, num1 =num1, num0
	fmt.Println(num0,num1)
}

匿名变量:

package main
import "fmt"
func main(){
	var tmp int
	num0, num1 := 10, 20
	tmp, _ = num0,num1    //下划线代表了当前位置变量的缺省
	fmt.Println(num0,num1,tmp)
}

通过如上操作之后,将变量位置用下环线代替,num1的值将不会在赋值语句中被使用,但_匿名变量配合函数返回值使用更加具有优势。

package main
import "fmt"
func test()(a,b,c int){
	return 1,2,3
}
func main(){
	num0, num1 := 10, 20
	num0,_,num1=test()
	fmt.Println(num0,num1)
}

此时,暂时不需要的部分将会在赋值语句中被缺省。

常量:与变量相反,则是程序运行期间无法改变的量,一般可以再不需要修改的核心数据声明时使用。

const pi float64=3.14159265

这样声明之后,如果在后面的程序中尝试修改pi这个值,则会报错。

常量的自动推导类型:

const pi=3.1415926

需要注意的是:在常量的自动推导类型中,运算符用的是“=”而非“:=”,这是与变量自动推导类型需要区分的。

枚举:iota

1.常量自动生成器,每隔一行自动累加1,同一行的赋值是一样的
2.只能为常量赋值使用
3.iota遇到const重置为0
4.可以只写一个iota,下面的常量会自动进行赋值

func main(){
	const(a,b=iota,iota	//a,b均为0
		c=iota	    //c为1 
	)		
	const d = iota		//d为0
	const(e=iota		//e=0
	    f		    //f=1
	    g		    //g=2
	)			
}

我们在Go语言中常用的基本数据类型有:

整型:int, uint(无符号整型)

实型:float32, float64 

复数型:complex32, complex64

字符型:byte

字符串型:string

下面正式开始介绍整型意外的基本数据类型:

布尔类型:bool

var a bool    //bool类型的声明
var b=false    //bool类型的自动推导
c:=true    //bool类型的自动推导

要注意的是:在Go语言中,bool类型与int类型不兼容。bool类型只有两种值:真true, 假false。

浮点型:float32

var a float32    //float32类型的声明
var b=3.14    //float32类型的自动推导
c:=3.14    //float32类型的自动推导

需要注意的是:在自动推导类型当中,浮点型的数据类型变为了float64,它比float32要更加大,更加精准。

字符型(ASCII):byte

package main
import "fmt"
func main(){
	ch:='a'
	fmt.Println(ch)    //使用基本打印函数输出ch
}

需要注意的是:使用基本打印函数打印输出ch时,输出的是97而不是a,而97就是a的ASCII码值。也就是说,在没有明确要求的情况下,字符型输出会打印出此字符对应的ASCII码值,这也证明了在Go语言中,字符型与整形是相互兼容的。如何解决此问题:我们需要用到格式化输出方法Printf()(将会在下文详细描述)。通过对比ASCII表,我们可以发现,在Go语言中类似其他语言,对英文字符大小写的转换我们可以通过加减32的方式来完成(小写字符ASCII值大于相应大写字符ASCII值 )。ASCII码表中转义字符不可见,无法打印(‘\’转义符号‘ \n’转义字符--换行)。

字符串形:string

package main
import "fmt"
func main(){
	str:="hello"
	fmt.Println(len(str))    //求取字符串长度
}

內建函数:len()  输出字符串长度。

字符与字符串的区别:

1.赋值时字符用‘’     字符串用“”
2.字符在赋值时只能输入一个字符(转移符除外)
3.字符串由一到多个字符所组成,字符串的结尾隐藏了“\0”结束字符,此字符不计入到长度中
4.字符串亦可以看做字符数组,下标从0开始 str[x]可以对相应下标的字符进行操作

复数型:complex64

package main
import "fmt"
func main(){
	t:=12+3.14i        //复数自动推导
	fmt.Println(real(t),imag(t))        //分别输出实虚部
}

需要注意的是:自动推导类型中,复述的类型为complex128.

內建函数:real()求实部,imag()求虚部。

Go语言的输出:这些输出函数都包含在fmt包中

Print()  基本输出函数

Println()  基本输出函数,自动换行

Printf()  格式化输出:格式化输出  把变量的内容放到占位处(%d)“\n”是换行符  在控制格式有自己的优势,更容易处理多个变量。

 

 我们在格式化输出时,常用的占位符有:

%d整形占位符

%c字符型占位符,课在上文中解决输出ASCII码问题,用%v也会出现整形输出的情况

package main
import "fmt"
func main(){
	ch:='a'
	fmt.Printf("%c",ch)    //使用格式化打印函数输出ch
}

%s字符串类型占位符

%f浮点型占位符,出现补0情况,可用%v优化

%t布尔类型占位符,由于整型与布尔类型不兼容,所以不能用%d代替

%T读取变量数据类型

%v自动匹配格式输出

输入:阻塞程序等待用户输入

fmt.Scanf(“%d”,&num)
fmt.Scan(&num)

需要注意的是:在输入语法中,量的前面需要加上取地址符&。

不同类型变量的多重声明和赋值:

var (        //不同类型多重声明
	a int
	b float64
)
a,b=10,3.14    //不同类型多重赋值

同时,我们也可以为其进行初始化:

const(
	a int = 10
	b float64 = 3.14
)

也可以运用自动推导类型:

const(
	i = 10
	j = 3.14
)
var (
	a = 10
	b = 3.14
)

类型的转换:

1.布尔类型与整型无法兼容,不能互相转换。

2.字节型与整型可以相互转换。

var ch=‘x’
var num int
num=int(ch)    //强制转换

var ch0 byte
var num0=100
ch0=byte(num0)    //强制转换

别名:

我们可以再Go语言程序中为关键字写一些别名

package main
import sysout "fmt"	//为包fmt起别名sysout
func main(){
	type lon int64	//为量int64起别名lon
	var num lon = 123456
	sysout.Println(num)
}

也可以多重别名:

type (
	lon int64
	char byte
)

Go语言中的运算符:

算数运算符:

 需要注意的是:Go语言不同于C++,运算符++与--在Go语言中之后后置没有前置。

关系运算符:

需要注意的是:关系运算符不可以范围连写,如11<=x<=13。

 逻辑运算符:

需要注意的是: 逻辑运算符往往配合关系运算符使用,非0就是真,0就是假 ,但bool与int不兼容。如:a>b||c<d。非则是对布尔类型取反。与则需要前后条件均真才会返回真,其他为假,其中如果第一个条件为假,第二个条件将不会被判断和运算。非则需要前后条件全假才会返回假,其他为真,其中如果第一个条件为真,第二个条件将不会被判断和运算。

 位运算符:不做详解

赋值运算符:

需要注意的是:与其他语言相相同,存在+=,-=类似的运算符,例如:a=a+b可以写为a+=b。

其他运算符:不做详解,多用于指针。

 运算符优先级:

需要注意的是:优先级越大,越先运算,同运算优先级采取从左到右的顺序运算。()可以改变运算的优先级,优先算()内部。

Go语言语法部分:顺序结构,选择结构,循环结构。

顺序结构:顾名思义,按从上到下顺序执行,不做详解。

选择结构:if,switch

if语句:基础格式: if  条件  {}

条件成立,即可执行if内的语句。

package main
import "fmt"
func main(){
	var num int = 5
	if num==5{
		fmt.Println("可运行")
	}
}

if也支持一个初始化语句,初始化语句和判断条件以分号相隔:

package main
import "fmt"
func main(){
	if num:=5;num==5{
		fmt.Println("可运行")
	}
}

if的多分支:if-else

package main
import "fmt"
func main(){
	var num int = 5
	if num==5{
		fmt.Println("直接条件成立")
	}else{
		fmt.Println("直接条件不成立")
	}
}

需要注意的是:else之后不再有条件。

if的多分支:if-else if-else

package main
import "fmt"
func main(){
	var num int = 5
	if num==5{
		fmt.Println("直接条件成立")
	}else if num > 5{
		fmt.Println("直接条件不成立")
	}else{	//这种情况则是num<5
		fmt.Println("第二条件不成立")
	}
}

对于上面的代码,我们也可以用以下代码代替:

package main
import "fmt"
func main(){
	var num int = 5
	if num==5{
		fmt.Println("直接条件成立")
	}
	if num > 5{
		fmt.Println("直接条件不成立")
	}
	if num < 5{	
		fmt.Println("第二条件不成立")
	}
}

对比来说,前者代码执行时整个if-else if-else块中只要存在一次条件成立则不会再判断下面的条件,而后者需要多次判断条件不会跳过,在代码效率上有所降低。

注意:各条件下的语法都不能相同,否则会报错。

switch语句:

package main
import "fmt"
func main(){
	var num int = 2
	switch num{        //关键字后不再加条件,而是加量
	case 1:fmt.Println("条件1成立")
	case 2:fmt.Println("条件2成立")
	case 3,4,5:fmt.Println("条件3成立")
	default:fmt.Println("无符合条件")
	}
}

与C++不同的是,case语句块不在需要加break(可主动写也可不写),语言默认跳出,但如果想按照不跳出调试,则需要在case块内加关键字:fallthrough。同理:各条件下的语法都不能相同,否则会报错。

switch也支持一个初始化语句,初始化语句和变量以分号相隔:

package main
import "fmt"
func main(){
	switch num:=2;num{
	case 1:fmt.Println("条件1成立")
	case 2:fmt.Println("条件2成立")
	case 3:fmt.Println("条件3成立")
	default:fmt.Println("无符合条件")
	}
}

switch后也可不附带条件,这时:

package main
import "fmt"
func main(){
	var score int =91
	switch{
	case score>90:fmt.Println("成绩为优秀")
	case score>80:fmt.Println("成绩为良好")
	case score>70:fmt.Println("成绩为中等")
	case score>=60:fmt.Println("成绩为及格")
	default:fmt.Println("成绩不及格")
	}
}

需要注意的是:switch后无条件,case后有对应条件,此程序需将case条件从大到小编写。

循环结构:for循环,range迭代器(Go语言中不写do-while/while)

for循环:基本格式:for 初始条件;判断条件;条件变化{}

package main
func main(){
	var tot int
	for i:=1; i<=100;i++{    //这时的i是局部变量
		tot+=i
	}
}

此程序完成了从1到100的累加。for循环执行过程:

1.由初始条件进入
2.判断条件是否为真
3.如果为真,执行循环;如果为假,跳出循环;
4.条件为真,进行条件变化
重复2,3,4步骤

range迭代器:返回两个值,下标及元素本身。更适合处理字符串类型数据

package main

import "fmt"

func main(){
	var str string="hello go"
	for i,data:=range str{	//i是下标(位置),data是元素本身    迭代读取元素更为简便
		fmt.Printf("%d=%c  \n",i,data)
	}
}

 如果使用for循环单独输出字符串中字符的下标和元素本身,则需要用i和str[i]来进行输出。

此处也可用匿名变量缺省,只获取单一变量:

for _,data:=range str{}

但如果全部条件缺省,则变成死循环,条件永远为真:

for {}

跳转语句:break与continue

break:可以用于跳出循环或者条件 ,一般配合if与for使用,如果嵌套多个循环则跳出最近内循环。

continue:跳过单次循环,不影响下一次循环,只能用在循环之中。

goto语句:大量程序下跳转较为复杂,不建议使用

package main
import "fmt"
func main(){
	fmt.Println("输出语句1")
	goto A        //定义标签
	fmt.Println("输出语句2")
	A:        //标签
	fmt.Println("输出语句3")
}

如此,则跳过输出语句2。但:

1.goto可以用在任何地方,但不能夸函数使用

2.实现跳转---无条件跳转

3.定义了标签才可以使用

程序结构的拓展:

1.多个包可以用import(包名1 包名2 …)

2.type 定义结构体类型 type variable_name struct{}

3.type 定义接口类型 type variable_name interface{}

可见性规则拓展:

1.函数名首字母为小写则为private

2.函数名首字母为大写则为public

拓展:

import"time"
    time.Sleep(time.second)//延时一秒

学习材料:01 go语言-02 快速入门go语言

猜你喜欢

转载自blog.csdn.net/qq_18800771/article/details/96642743