go语言基础入门

一、基础语法与代码风格

源文件后缀名.go,入口是main()函数,main()函数必须在main包。

go语言严格区分大小写,大写公开,小写私有。

每条语句后面不需要分号,编译器会自动加上分号。(你写分号不会报错。)

每一行必须只写一句,i++必须独占一行。

强制首花括号行尾风格,不在行尾编译报错。

引入的包和定义的变量必须使用,如果不用则编译报错。

先写变量名,再写类型名。

函数允许有多个返回值。

函数本身也是一种数据类型,可以作为参数传递。

变量不赋值,默认给零值。

与Java不同,Java的所有变量和方法都写在类的内部,以类为单位组织代码。Golang则是包内写变量、方法,以包为单位组织代码。

如果代码过长,可以换行保持优雅,注意不要在括号处换行。
注释风格和Java一样,//行注释,/**/块注释

二、编译运行

go是跨平台的静态编译型语言,可直接编译为机器码运行,不依赖虚拟机。
go编译器在编译期间可检查出大部分问题。
go具备自动垃圾回收机制,而且加入了逃逸分析算法,提升GC效率。
go是一种强类型语言,不支持类型的自动隐式转换。

编译命令:go build main.go
运行:直接双击或命令行输入main.exe
编译+运行命令:go run main.go

三、变量与常量

1、变量

go定义变量的四种方法:

var a int       //若不赋值,则默认值为0
var b int = 10  //声明同时赋值
var c = 15      //省略类型,可以自动推断
d :=20          //这种简写不可用于定义全局变量

2、常量

go常量定义与枚举
常量定义的关键字:const
常量必须在声明的同时赋值。
常量const关键字不能省略,所以也不能用:=。
例如:

const a int = 8//定义整型常量,赋值为8
const b ="abc"//定义常量并赋值,省略类型,推断为字符串

3、枚举

枚举常用builtin包中成员iota(问:为什么builtin包中的iota用const关键字定义,却能一直递增?它到底是常量还是变量?)

const (
	a,b = iota+1,iota+2 //iota = 0, a = 0+1, b=  0+2
	c,d 				//iota = 1, c = 1+1, d = 1+2
	e,f                 //iota = 2, e = 2+1, f = 2+2
	g,h = iota*2,iota*3 //iota = 3, g = 3*2, h = 3*3
	i,k                 //iota = 4, i = 4*2, k = 4*3
)

四、函数

1、函数的格式:

func(接收体)函数名(参数列表)(返回值列表){
	函数体
	return 返回值列表
}

2、多返回值

func show1(a int,b int) int{
  c := a+b
  return c
}
/*多返回值:匿名返回*/
func show2(a int, b int)(int string){
	c :=a+b
	d :="hello"
	return c,d
}
/*多返回值:有形参名称的返回*/
func show3()(c int,d string){
	fmt.Println(c)//此时值默认为0
	c = 3
	d = "hi"
	return // 虽然return后面什么也不跟,但c和d是被返回去的
}

3、接收体

接收器是golang写结构体成员方法的常用语法。

函数除了函数名、参数、返回值,还有接收器的概念,接收器只能有一个,接收器的概念类似于面向对象概念中的this或self,传入的接收器对象(一般要加星以便可对其修改),在函数中可以对其进行修改。
go语言方法和接收器
go函数声明语法:函数名前的括号内的东西

五、流程控制

1、if语句

if(表达式){
	//todo
}else if(表达式){
	//todo
}

注意:1、表达式可以是bool值,但不允许用其他数据类型(不存在“非零即真”的情况)
2、在if语句中可以进行赋值操作,用分号与判断表达式隔开
3、表达式括号可省略。

if a:=3;a>1{
    fmt.Println("a=3;a>1")//成功输出a=3;a>1
}

2、switch语句

2.1、switch语句常规用法

与其他语言不同,case中默认带break,也就是说不会自动穿透。
匹配不到则执行default语句块,default不是必须的。
case表达式可以有多个,用逗号隔开。意思是都匹配。
case表达式如果是常量则要求不能重复,常量会骗过编译器。
switch和case的表达式数据类型要一致。

var key byte
fmt.Scanf("%c",&key)
switch key{
	case 'a': 
		fmt.Println("周一")
	case 'b':
		fmt.Println("周二")
	case 'c': 
		fmt.Println("周三")
	case 'd':
		fmt.Println("周四")
	case 'e': 
		fmt.Println("周五")
	case 'f','g':
		fmt.Println("周末")
	default:
		fmt.Println("输入有误")
}

2.2、switch语句不加表达式,case范围判断

这是go语言的特性,其他语言不可以。

var age int
fmt.Scanf("%d",&age)
switch{
	case age<18:
		fmt.Println("未成年")
	case age>=18&&age<40:
		fmt.Println("青壮年")
	case age>=40&&age<60:
		fmt.Println("中年")
	case age>=60:
		fmt.Println("老年")
	default:
		fmt.Println("输入有误")
}

2.3、switch穿透——fallthrough

如果case语句块后面有fallthrough关键字,则会穿透,不判断下一个case,直接执行下一个case的语句块。默认只能穿透一层。

case 10:
	fmt.Println("ok1")
	fallthrough//如果匹配到10,输出“ok1”,此处fallthrough会穿透case 20
case 20: //如果是穿透来的,不判断,直接执行下面语句块
	fmt.Println("ok2")

3、for循环

3.1、多次循环

for i:=0;i<10;i++{
	//todo
}

3.2、永远循环

for{
	//一般配合break使用,否则就是死循环。有的语言如Java不允许这样。
}

3.3、条件循环、break跳出循环

golang中没有while和do……while……
一般用for和if…break配合实现同样的效果

for{
	//todo
	if(){
		break;
	}
}

3.4、break+标签

标签用于标示break跳出的是哪一层循环。
用法:以双重for循环为例,break跳出的是哪个循环,就把标签写到那个for上方,标签后面要有冒号。

func main(){
	//label1:
	for i := 1; i < 10; i++ {
		label2:
		for j := 1; j <= i; j++ {
			fmt.Print(j," * ",i," = ",i*j,"  ")
			if(i==7&&j==3){
				//break label1;
				break label2;
			}
		}
		fmt.Println()
	}
}

3.5、for-range遍历

需要数组、切片、map等数据结构前置知识。
示例:

func RangeSlice(slice []int) {
    for index, value := range slice {
        fmt.Println(index,value)
    }
}

六、数组与切片

数组array是值类型,长度固定,切片slice是引用类型,有长度length和容量capacity。

1、如何初始化一个数组?

func main() {
	var testArray [3]int                        //数组会初始化为int类型的零值
	var numArray = [3]int{1, 2}                 //使用指定的初始值完成初始化
	var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
	fmt.Println(testArray)                      //[0 0 0]
	fmt.Println(numArray)                       //[1 2 0]
	fmt.Println(cityArray)                      //[北京 上海 深圳]
}

2、如何初始化一个切片?

	var a []string              //声明一个字符串切片,未赋值,为nil
	a = make{[]string,3,5}		//开辟内存空间,长度3,容量5,默认元素3个""
	var b = []int{1,2,3}       //声明一个整型切片并初始化
	var c = []bool{false, true} //声明一个布尔切片并初始化
	var d = []bool{false, true} //声明一个布尔切片并初始化

	e := make([]int, 2, 10) //用make()函数自定义容量长度的切片。
	fmt.Println(e)      //[0 0]
	fmt.Println(len(e)) //2
	fmt.Println(cap(e)) //10

3、如何查看切片的长度、容量?

用内置函数len() cap()查看

fmt.Println(len(b),cap(b))

4、数组在函数中是值传递,切片在函数中是引用传递

func main(){
	nums := [5]int{1,1,1,1,1}
	changeArray(nums)
	fmt.Println(nums)//打印结果:[1 1 1 1 1]
	slice :=[]int{1,1,1,1,1}
	changeSlice(slice)
	fmt.Println(slice)//打印结果:[3 1 1 1 1]
}
func changeSlice(slice []int){
	slice[0] = 3
}
func changeArray(array [5]int){
	array[0] = 3
}

5、切片如何追加元素?

slice :=[]int{1,8,9}
slice = append(slice,5)
fmt.Println(slice)//打印结果:[1 8 9 5]

6、切片在扩容的时候,长度、容量、内存地址是如何变化的?

	var numSlice []int
	for i := 0; i < 10; i++ {
		numSlice = append(numSlice, i)
		fmt.Printf("%v  len:%d  cap:%d  ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
	}
输出:
[0]  len:1  cap:1  ptr:0xc0000a8000
[0 1]  len:2  cap:2  ptr:0xc0000a8040
[0 1 2]  len:3  cap:4  ptr:0xc0000b2020
[0 1 2 3]  len:4  cap:4  ptr:0xc0000b2020
[0 1 2 3 4]  len:5  cap:8  ptr:0xc0000b6000
[0 1 2 3 4 5]  len:6  cap:8  ptr:0xc0000b6000
[0 1 2 3 4 5 6]  len:7  cap:8  ptr:0xc0000b6000
[0 1 2 3 4 5 6 7]  len:8  cap:8  ptr:0xc0000b6000
[0 1 2 3 4 5 6 7 8]  len:9  cap:16  ptr:0xc0000b8000
[0 1 2 3 4 5 6 7 8 9]  len:10  cap:16  ptr:0xc0000b8000

结论:会自动扩容,每次扩容是cap翻倍,扩容后内存地址变了。

七、channel

1、如何初始化channel?

	var c chan int
	c = make(chan int, 9)//容量为9的有缓冲的chan
	//c = make(chan int)//无缓冲的chan

2、如何传入和取出数据?

//在一个goroutine中传入数据:
c <- 666
//......
//在另一个goroutine中取出数据:
num := <- c

八、map

map是引用类型,是乱序键值对。类似于Java中的HashMap。

简单运用,示例:

func main(){
	var m1 map[string]string//声明map
	m1 = make(map[string]string,10)//初始化m1
	m1["China"] = "Beijing"//给m1存入值
	m1["Japan"] = "Tokyo"
	m1["USA"] = "NewYork"
	m1["Rusia"] = "Moscow"
	fmt.Println(m1["USA"])//通过key从m1中取出值
	delete(m1,"Japan")//删除元素
	m1["USA"] = "Washington"
	fmt.Println(m1," length of m1 : ",len(m1))//打印m1,取m1的元素数量
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值