基础语法
在我们开始学习 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)
}
}