1.走近Go语言基础语言
Go是一种并发、高效的编程语言,由Google公司开发,于2009年首次亮相。Go语言的设计注重于提高程序员的生产力,同时具有高效、可靠性和可扩展性等特点。它采用垃圾回收机制,拥有较好的内存管理能力。Go语言还内置了对并发编程的支持,包括goroutine和channel,能够轻松地处理并发编程中的多线程问题,从而更加高效地利用多核处理器。此外,Go语言还具有简洁、易读的语法,便于开发者编写高效、简洁的代码。
基础语法 - helloworld
package main//代表这个文件属于main包的一部分,导入了程序的入口文件
//导入标准库里的fmt包,输入输出字符串
import (
"fmt"
"math"//从这里来导入库
"time"
)
func main() {//这个花括号还必须得在这
fmt.Println("hello world")//小技巧:鼠标放在fmt上,会出现一个链接,有fmt包里的内容
}
运行
go run ./文件目录+文件名 //直接运行
go bulid ./文件目录+文件名 //先编译成二进制文件
./文件目录+文件名 //直接运行
基础语法 - 变量
var a = "initial"
//var 变量名 = 值 //var代表变量 然后用值会自动推导类型
var b,c int = 1,2
//也可以显示的定义类型 在变量名后 + 类型
f := 3.14
//另一种声明变量的方式 变量名 := 值
g := a + "foo"
//Go语言中字符串属于内置类型,就像C++一样重载运算符
const s string = "constant"
//声明常量 把var变为const 在Go里的常量没有确定的类型,根据使用的上下文来自动确定类型
基础语法 - if else
if 7%2 == 0 {//条件不带(),如果带了保存时编译器会自动去掉,然后就是花括号必须在这个位置
} else {
}
if 7%2 == 0 {
} else if {
} else {
}
基础语法 - 循环
for {//最简单的死循环
}
for j := 0; j<5; j++ {//这快没有 ++j
//也跟C++一样,分三段,任何一段都可以省略
}
for j := 5; j<10; j++ {
if j%2==0 {
//continue 这两个的作用也跟C++一样
//break
}
}
基础语法 - switch
a := 2
switch a {//与C++不同的是,这里的变量也不加()
case 1://并且每一条case语句完是不需要加break的
//
case 2:
//
case 3,4:
//
default:
//
}
//比C/C++更强大,可以使用任意的类型:字符串、结构体,并且可以代替任何一个if-else语句
t := 4
switch {//在switch后不加任意变量,在case中写条件分支
case t<12 :
//
default:
}
基础语法 - 数组
在Go中不太用数组,因为长度是固定的
var a [5]int
a[4] = 100
b := [5]int{1,2,3,4,5}
var c [2][3]int
基础语法 - 切片
重点不用数组,用切片
切片不同于数组,是可变长度的,可以在任意时刻更改
s := make([]string,3)//创建一个切片,可以像数组一样使用
s[0] = "a"
s[1] = "b"
s[2] = "c"
len(s)//长度 3
//切片的原理:长度+容量+指向数组的指针
s = append(s,"d")//必须给s,如果容量不够,会扩容指向一个新的数组
c := make([]string,len(s))
copy(c,s)
fmt.Println(s[1:3])//左包含右不包含
fmt.Println(s[:3])//
fmt.Println(s[1:])//
基础语法 - map
// key value
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) //map[one:1 two:2]
fmt.Println(len(m))//2
fmt.Println(m["one"])//1
fmt.Println(m["unknow"])//0
r,ok := m["unknow"]
fmt.Println(r,ok)//0 false
delete(m,"one")//删除kv对
m2 := map[string]int{"one":1,"two":2}
var m3 := map[string]int{"one":1,"two":2}
基础语法 - range
nums := []int{1,2,3}
for i,num := range nums{
}
m := map[string]string{"a":"A","b":"B"}
for k,v := range m{//第一个参数为k,第二个v,且必须在下文要用到
fmt.Println(k,v)//b 8;a A
}
for k := range m {
fmt.Println("key:",k)// key:a;key:b
}
基础语法 - 函数
func add(a int,b int) int {//类型在后
return a + b
}
//可以返回多个值,第一个是真正的值,第二个值是错误信息
func exists(m map[string]string,k string) (v string,ok bool){//返回值再后
v,ok = m[k]
return v,ok
}
基础语法 - 指针
//go中的指针使用有限,常用来修改值
func add(n *int) {
*n += 2
}
func main() {
n := 5
add(&n)//取n的地址
fmt.Println(n)//7
}
基础语法 - 结构体
type user struct {
name string
passwd string
}
func main() {
a := user{name:"wang",passwd:"1024"}//可以用结构体名称初始化一个结构体变量
b := user{"wang","1024"}
c := user{name:"wang"}//若只写出了字段的一部分的话,也可以只写字段的一部分值,没有初始化的字段初始化为空值
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a)//{wang 1024}
fmt.Println(checkPassword(a,"haha")//false)
}
func checkPassword(u user,password string)bool{
return u.password == password
}
基础语法 - 结构体方法
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {//把u user 搬到函数名前加(),从一个普通函数变为一个类成员函数,有点像C++的this指针的调用一样
return u.password == password
}
func (u *user)resetPassword(password string) bool {//带指针就可以对结构体进行修改,不要问为什么会用就行
return u.password = password
}
func main() {
a := user{name:"wang",passwd:"1024"}
a.resetPassword("2048")
fmt.Println(a,checkPassword("2048"))//true
}
基础语法 - 错误处理
package main
import (
"errors"
"fmt"
)
type user struct {
name string
passw string
}
func findUser(users []user,name string) (v *user,err error) {
for _,u := range users {//_代表空标识符,忽略该循环变量的值,避免编译器因未使用变量而产生的警告,Go中未使用变量和包就会有警告
if u.name == name {
return &u,nil//如果正确,那么返回原本的结果和nil,nil代表空指针
}
}
return nil,errors.New("not found")//出现错误的话,可以返回nil和一个error,这里相当于new了一个变量
}
func main() {
u,err := findUser([]user{{"wang","1024"}},"wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)//wang
if u,err := findUser([]user{{"wang","1024"}},"li");err != nil {
fmt.Println(err)//not found
return
} else {
fmt.Println(u.name)
}
}