Go语言入门指南:基础语法和常用特性解析 | 青训营

73 阅读5分钟

本文对Go语言的基础语法和常用特性进行总结。

基础语法

首先看看第一段程序Hello! World长什么样子,代码如下:

package main 
import "fmt"	
func main() {
	fmt.Println("Hello World")
}

变量

变量的声明、赋值与使用

package main 
import "fmt"
func main(){
	// 1.变量的声明
	var age int
	// 2.变量的赋值
	age = 18
	// 3.变量的使用
	fmt.Println("age = ", age)
	// 声明和赋值可以合成一句
	var age2 int = 19
	fmt.Println("age2 = ", age2)
	// 不可以在赋值时给予不匹配的类型
	// var age3 int = 3.14
}

在golang中变量有四种定义方式,以下包括全局变量的使用:

package main
import "fmt"
// 全局变量;定义在函数外
var n7 = 100
var n8 = 9.7
// 上面的全局变量写法比较麻烦,可以一次性声明
var (
	n9 = 500
	n10 = "netty"
)
func main(){
	// 第一种:指定变量的类型并且赋值
	var num int = 18
	fmt.Println(num)
	// 第二种:指定变量的类型,不赋值,使用默认值
	var num2 int
	fmt.Println(num2) // 0
	// 第三种:如果没有写变量的类型,通过值来推导变量的类型
	var name = "zjy"
	fmt.Println(name)
	// 第四种:省略var,使用 := 来声明并且赋值,不能写为 =
	sex := "man"
	fmt.Println(sex)

	fmt.Println("--------------------")
	// 声明多个变量
	var n1,n2,n3 int
	fmt.Println(n1,n2,n3)

	var n4,name2,n5 = 100,"zjy",3.14
	fmt.Println(n4,name2,n5)

	// 声明多个变量的简写
	n6,height := 100,3.45
	fmt.Println(n6,height)

	// 输出全局变量
	fmt.Println(n7,n8,n9,n10)
}

数据类型

整数型

Golang程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型

浮点型
package main
import "fmt"

func main(){
	// 定义浮点类型的数据
	var num1 float32 = 3.14
	fmt.Println("num1 = ",num1)
	// 可以表示正浮点数也可以表示负浮点数
	var num2 float32 = -3.14	
	fmt.Println("num2 = ",num2)
	// 浮点数可以用十进制表示也可以用科学记数法表示形式,E大小写都可以
	var num3 float32 = 314E-2
	fmt.Println("num3 = ",num3)
	var num4 float32 = 314e-2
	fmt.Println("num4 = ",num4)
	// 浮点数可能会有精度损失,通常用float64
	var num5 float32 = 3.141592653	
	fmt.Println("num5 = ",num5)
	var num6 float64 = 3.141592653
	fmt.Println("num6 = ",num6)
	// golang中的浮点数默认是float64类型
	var num7 = 3.14
	fmt.Printf("num7的数据类型是%T\n",num7)

}
字符型

字符型即char类型在golang中对应的是byte

package main
import "fmt"

func main(){
	// 定义字符类型数据
	var c1 byte = 'a'
	fmt.Println("c1 = ",c1) // 97
	var c2 byte = '0'
	fmt.Println("c2 = ",c2) // 48
	// 如果直接输出byte类型的数据,输出的是对应的字符
	var c3 int = '中'
	fmt.Println("c3 = ",c3) // 20013
	// 字母、数字、符号都可以直接使用byte类型,底层都对应ASCII码值
	// 汉字字符底层对应的是Unicode码值,使用byte类型会溢出,所以使用int类型
	// 总结:Golang中的字符对应使用的是UTF-8编码(Unicode是对应的字符集,UTF-8是Unicode的其中一种实现)
	var c4 byte = 'A'+19 // 想显示对应的字符,需要使用格式化输出
	fmt.Printf("c4 = %c\n",c4) // T
}

golang中也提供string即字符串

package main
import "fmt"
func main() {
	// 1.定义一个字符串
	var s1 string = "hello"
	fmt.Println(s1)
	// 2.字符串是不可变的: 字符串一旦定义好,其中的字符的值不能改变
	var s2 string = "abc"
	fmt.Println(s2)
	// 3.字符串的表示形式
	// (1)如果字符串中没有特殊字符,字符串的表示形式用双引号
	var s3 string = "hello"
	fmt.Println(s3)
	// (2)如果字符串中有特殊字符,字符串的表示形式用反引号
	var s4 string =`hello\nworld`
	fmt.Println(s4)
	// 4.字符串的拼接
	var s5 string = "hello" + "world"
	s5 += "!"
	fmt.Println(s5) // helloworld!
	// 当一个字符串过长时,可以分行书写,+号必须在上一行的末尾
	var s6 string = "hello" + "world" +
		"hello" + "world" +
		"hello" + "world"
	fmt.Println(s6) 
}
布尔类型
package main 
import "fmt"

func main(){
	// 测试布尔类型的数值
	var b1 bool = true
	fmt.Println("b1 = ",b1) // true
	var b2 bool = false
	fmt.Println("b2 = ",b2) // false
	// 布尔类型不能参与数值运算,也不能与其他类型进行转换
	var b3 bool = 5 < 9
	fmt.Println("b3 = ",b3) // true

}
指针的使用
package main
import "fmt"
func main(){
	var age int = 18
	// &+变量名表示取地址
	fmt.Println(&age)
	// var表示声明一个变量
	// ptr表示指针变量的名字
	// ptr对应的类型是: *int(指向int类型的指针)
	var ptr *int = &age
	fmt.Println(ptr)
	fmt.Println("ptr的地址是:",&ptr)
	// 获取ptr指针指向的数据
	fmt.Println("ptr指针指向的数据是:",*ptr)
}

运算符注意事项

package main
import "fmt"
func main(){
	var a int = 10
	a++
	fmt.Println(a)
	a--
	fmt.Println(a)
	// ++,--只能独立使用,不能参与运算
	// var b int = a++ // 编译会报错
	// ++,--只能写在变量的后面,不能写在变量的前面
	// ++a // 编译会报错
}

分支结构

package main
import "fmt"
func main(){
    //给出一个学生分数:
    var score int = 87
    //根据分数判断等级:
    //switch后面是一个表达式,这个表达式的结果依次跟case进行比较,满足结果的话就执行冒号后面的代码。
    //default是用来“兜底”的一个分支,其它case分支都不走的情况下就会走default分支
    //default分支可以放在任意位置上,不一定非要放在最后。
    switch score/10 {
        case 10 :
                fmt.Println("您的等级为A级")
        case 9 :
                fmt.Println("您的等级为A级")
        case 8 :
                fmt.Println("您的等级为B级")
        case 7 :
                fmt.Println("您的等级为C级")
        case 6 :
                fmt.Println("您的等级为D级")
                // fallthrough //fallthrough语句可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的
        case 5 :
                fmt.Println("您的等级为E级")
        case 1,2,3,4 : // case后面可以跟多个表达式,用逗号分隔
                fmt.Println("您的等级为F级")
        default:
                fmt.Println("您的成绩有误")
    }
}

循环结构

package main
import "fmt"
func main(){
	//实现一个功能:求和: 1+2+3+4+5:
    //求和:
    //利用for循环来解决问题:
    var sum int = 0
    for i := 1; i <= 5; i++ {
        sum += i
    }
    
    //输出结果:
    fmt.Println(sum) //15
    // for循环的语法格式:
    // for 初始表达式; 布尔表达式(条件判断); 迭代因子 {
    //  循环体;-->反复重复执行的内容
    // }
    // 注意:for的初始表达式 不能用var定义变量的形式,要用:=
	 //定义一个字符串:
	var str string = "hello golang你好"
	for i, value := range str {
		fmt.Printf("索引为:%d,具体的值为:%c \n", i, value)
	}
	//对str进行遍历,遍历的每个结果的索引值被i接收,每个结果的具体数值被value接收
	//遍历对字符进行遍历的
}

常用特性

函数

golang可以返回多个参数

func cal(num1 int,num2 int)(int,int){
	var sum int = num1 + num2
	var sub int = num1 - num2
	return sum,sub
}

可以使用 _ 来忽略某个返回值

sum1,_ := cal(19,89)

init函数

init是golang中的初始化函数,可以用来进行一些初始化的操作,每一个源文件都可以包含一个init函数,该函数会在main函数执行前,被Go运行框架调用

匿名函数

golang支持匿名函数,如果我们某个函数只是希望使用一次,可以考虑使用匿名函数

package main

import (
	"fmt"
)

// 匿名函数全局调用
var add = func(num1 int, num2 int) int {
	return num1 + num2
}

func main() {
	// 定义匿名函数,定义的同时调用
	result := func(num1 int, num2 int) int {
		return num1 + num2
	}(10, 20)

	fmt.Println(result)

	// 定义匿名函数,赋值给变量
	f := func(num1 int, num2 int) int {
		return num1 + num2
	}
	result = f(10, 20)
	fmt.Println(result)

	// 调用全局匿名函数
	result = add(10, 20)
	fmt.Println(result)
}

defer

在函数中,我们经常需要创建资源,为了在函数执行完毕后,及时的释放资源,我们可以使用defer关键字

func foo() int {
	a, b := 3, 5
	c := a + b
	defer fmt.Println("111", c) // defer注册 会在函数结束前执行
	fmt.Println(c)
	// defer注册时会把相关的值拷贝进去,所以c的值不会改变
	defer func() {
		fmt.Println("333", c)
	}()
	c = 100
	defer fmt.Println("222", c)
	return c
}

切片

切片(slice)是golang中一种特有的数据类型

func main() {
	// 切片的定义
	arr := make([]int, 3, 5)
	// 切片的赋值
	arr[0], arr[1], arr[2] = 2, 7, 9
	// 切片的追加
	brr := append(arr, 8)
	brr = append(brr, 8)
	arr[0] = 4
	fmt.Println(brr[0])
	brr = append(brr, 8)
	arr[1] = 5
	fmt.Println(brr[1])
	fmt.Println(len(brr), cap(brr))
	fmt.Println(len(arr), cap(arr))
	// 切片的遍历
	for i, ele := range arr {
		fmt.Printf("%p %p %d %d\n", &ele, &arr[i], ele, arr[i])
	}
}