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

63 阅读6分钟

基础语法

在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。

Go 语言的基础组成有以下几个部分:

  • 包声明
  • 引入包
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释

变量

变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。 变量可以通过变量名访问。 Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

在GoLang中可用 var 声明变量,用 const 声明常量

数据类型有以下几种

  • 布尔型:布尔型的值有true、false
  • 数字类型:int、float32、float64
  • 字符串类型
  • 派生类型:指针(pointer)、数组、结构化(struct)、Channel、函数、切片、接口、Map

在变量名后可接其类型,没有类型时系统会根据值自行判断类型

可以用英文逗号分隔同时声明多个变量

变量若没有初始化,默认为零值:数字类型为0,字符串为””,布尔型为false,一些类型为nil

//例:
package main
import(
	"fmt"
)

/*常量还可用作枚举:
const(
	Unknow=
	Female = 1
	Male = 2
)*/

func main(){
	var a = "hello"  //字符串 可写为var a string = "hello"
	var b, c int = 1, 2
	var d = true
	var e float64

	f := float32(e)
	/*将e强转,此语句为var的简便写法,相当于:
	var f float32
	f = e
	*/
}

条件判断语句

if-else

if-else语句中的条件不需要加上括号包起来

//例:
package main
import(
	"fmt"
)
func main(){
	if 7%2 == 0{
		fmt.Println("7 is even")
	}else{
		fmt.Println("7 is odd")
	}

	if num :=9; num < 0 {
		fmt.Println(num, "is negative")
	}else if num < 10{
		fmt.Println(num, "has 1 digit")
	}else{
		fmt.Println(num, "has mutiple digits")
	}
}

switch

package main
import(
	"fmt"
	"time"
)
func main(){
	a := 2
	switch a{
	case 1:
		fmt.Println("one")
	case 2:
		fmt.Println("two")
	case 3,4:
		fmt.Println("three or four")
	default:
		fmt.Println("other")
	}

	t := time.Now()
	switch{
	case t.Hour() < 12:
		fmt.Println("before noon")
	}
	default:
		fmt.Println("afternoon")
}

循环

for

go中的循环没有while,只有for,同时循环中可以使用break、continue、goto

package main
import(
	"fmt"
)
func main(){
	for true{ //此次的true也可省略
		fmt.Println("这是无限循环")
		//break
	}
	
	i := 1
	for i<=3 {
		fmt.Println(i)
		i += 1
	}

	for j:= 1; j<=3; j++ {
		if j == 2 {
			continue
		}
		fmt.Println(j)
	}
}

数组以及切片

数组有以下两种声明方式,并且同样有二维数组等

package main
import(
	"fmt"
)
func main(){
	var a [5]int
	a[4] = 100
	fmt.Println(a[4],len(a)) // 100,5

	b := [5]int{1,2,3,4,5}

	var twoD [2][3]int
	for i := 0; i < 2; i++{
		for j := 0; j < 3; j++{
			twoD[2][3] = i + j
		}
	}

}

切片(Slice)是对数组的抽象

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

var a []String  //可通过声明未指定大小的数组来定义切片,切片不需要说明长度

var slice1 []String = make([]string, 3)
slice1 := make([]string,3) //上述语句的简化
slice1[0] = "a"
slice1[1] = "b"
slice1[2] = "c"
slice1 = append(slice1, "d")  //通过append函数增加内容
slice1 = append(slice1,"e","f")

c := make([]string, len(s))
copy(c,slice1) //将slice1内容复制到c

fmt.Println(slice1[2:5])  // [c d e]
fmt.Println(slice1[2:])   // [c d e f]
fmt.Println(slice1[:5])   // [a b c d e]

Map

Map(引用类型)是一种无序的键值对集合,通过key来检索数据,键不存在返回类型的零值

package main
import(
	"fmt"
)
func main(){
	m := make(map[string]int)  //创建一个空Map,键string,值int
	m["one"] = 1
	fmt.Println(m["unknow"])   //0
	delete(m,"one")            //删除键值对

	v, ok := m["unknow"]       //获取键值对
	fmt.Println(v,ok)          // 0 false,表示键不存在

	m := make(map[string]int, 10)//创建初始容量为10的map
  fmt.Println(len(m))          //获取长度

	m := map[string]int{         //通过字面量创建map
		"apple" : 1,
		"banane" : 2,
		"orange" : 3
	}

	for k,v := range m {         //遍历
		fmt.Printf("key = %s, value = %d\n", k, v)
	}
}

Range

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合map中返回 key-value 对。

//使用格式
for key, value := range oldMap{
	newMap[key] = value
}

//只想读value或key有以下两种方法
for key := range oldMap{
	newKey = key
}

for _, value := range oldMmap{
	newMap[newkey] = value
}

函数

函数定义解析:

  • func:函数由 func 开始声明
  • function_name:函数名称,参数列表和返回值类型构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。
func function_name( [parameter list] ) [return_types] {
   //函数体
}

package main
import(
	"fmt"
)

func add(a int, b int) int{
	return a + b
}

func exists(m map[string]string, key string) (v string, ok bool){
	v,ok = m[key]
	return v,ok
}

func main(){
	a,b := 1, 2
	c := add(a,b)
	
	m := map[string]string{"baidu":"百度", "google":"谷歌"}
	v,ok := exists(m,"百度")
	
}

指针

一个指针变量指向了一个值的内存地址。取地址符是 &

package main
import(
	"fmt"
)

func add2(n int){
	n += 2
}

func add2P(n *int){
	*n += 2
}

func main(){
	var p *int   //指针的声明

	n := 2
	add2(n)
	fmt.Println(n)  //2
	add2P(&n)
	fmt.Println(n)  //4
}

结构体

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。

如果要访问结构体成员,需要使用点号 . 操作符,格式为:结构体.成员名

package main
import(
	"fmt"
)

type user struct{
	name string
	password string
}

func main(){
	user1 := user{"张三","123456"}  //声明方法一
	user2 := user{name:"李四"}      //声明方法二
	user2.password = "12345"
	var user3                       //方法三
	user3.name = "王五"
	USER3.password = "1234"

	fmt.Println(checkPassword(u1,"123456"))  //true
	fmt.Println(checkPassword(&u2,"123456")) //false
	fmt.Println(u1.checkPassword3("123456")) //true
	fmt.Println(u3.checkPassword4("1234"))   //true
}

func checkPassword(u user, password string) bool {
	return u.password == password
}

func checkPassword2(u *user, password string) bool{
	return u.password == password
}

func (u user) checkPassword3(password string) bool{  //结构体方法
	return u.passowrd == password
}

func (u *user) checkPassword4(password string) bool{  //结构体方法
	return u.passowrd == password
}

错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error 类型是一个接口类型,我们可以在编码中通过实现 error 接口类型来生成错误信息,使用 errors.New 可返回。

package main
import(
	"fmt"
	"errors"
)

type user struct{
	name string
	password string
}

func findUser(users []user, name string) (u *user, err error){
	for _, u := range users{
		if u.name == name{
			return &u, nil
		}
	}
	return nil, errors.New("Not Found")
}

func main(){
	u, err := findUser([]user{{"wang","1234"}}, "wang")
	if err != nil{
		fmt.Println(err)
		return
	}
	fmt.Println(u.name)    //wang

	if u, err := findUser([]user{{"wang", "1234"}}, "li"); err != nil{
		fmt.Println(err)     //Not Found
		return 
	}else{
		fmt.Println(u.name)
	}
}