准备
go不需要麻烦的jre。直接运行。
在官网下载golang
编译器选vscode就好,在插件那里下一下需要的插件。或者用Goland,这是Jetbrain的产品,收费的,学生免费。
基础语法
先来最简单的helloworld
package main // 定义包名,表明这是一个可执行程序的入口包
import (
"fmt" // 导入 fmt 包,用于格式化输入输出
)
func main() { // 定义 main 函数,程序的入口点
fmt.Println("hello world") // 调用 fmt.Println 函数打印 "hello world" 到控制台
}
要运行的话使用go run命令。
go run /cloudide/workspace/houduanrumen/01-走进Go语言基础语法/01-hello/main.go
也可以用go build先编译成二进制文件,再运行
go build /cloudide/workspace/houduanrumen/01-走进Go语言基础语法/01-hello/main.go
./main
变量
变量定义两种方式
var a = "initial"这种根据变量自己判断类型,和js一样。也可以指定类型var b, c int = 1, 2
f := float32(e)这是第二种。强转了类型再给f。:用在短变量声明里。
字符串内置,可以直接+加号连接 g := a + "foo"
条件判断
if语句后面不跟括号(跟了也被抹掉)。接着必须跟大括号,不跟报错
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
switch也是不用加括号()。有一个不同点是,go 里面switch的case不用加break。而且case后面可以跟变量表达式
t := time.Now()
switch {//这里甚至不用写条件
case t.Hour() < 12:
fmt.Println("It's before noon")//没有break照样ok
default:
fmt.Println("It's after noon")
}
循环
go里面只有for循环。也是不加括号。
for{//不加条件也可以
break
}
for j := 7; j < 9; j++ {
fmt.Println(j)
}
for i <= 3 {//加一个判断的也行,和while一样
fmt.Println(i)
i = i + 1
}
数组
这么声明var a [5]int和b := [5]int{1, 2, 3, 4, 5},二维就是两个var twoD [2][3]int
相比数组,还是slice好用。
slice
这里是创建可变长度的slices := make([]string, 3)
要想在后面增加内容,用append函数:s = append(s, "d")这里是把字符串‘d’赋值给s。在go中,slice其实是存了长度、容量和指向数组的指针。要是‘d’加进去s容量不够了,就开个新的大点的数组,s指向它,把‘d’塞进去。
c := make([]string, len(s))//也可以这样,c复制了s,话跟s一样长
copy(c, s)
像python一样,也能切片操作fmt.Println(s[2:5]) ,但是不能负数索引
map
就是哈希。m := make(map[string]int)这么创建。string索引int值。 如果输出是无序的输出。
m["one"] = 1one跟1连成对了。
delete(m, "one")删除了。
如果取不存在的键值对,会取出对应类型的零值。
输出:
range
用range可以快速遍历
//对数组是弄出索引和值
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
//对map是key,value
for k, v := range m {
fmt.Println(k, v) // b 8; a A
}
for k := range m {
fmt.Println("key", k) // key a; key b
}
函数
声明时函数类型写在后面。
func add2(a, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok= m[k]//这里ok表示是否有值返回,不存在这个键对应的值就false
return v, ok
}
指针
指针跟c++差不多,在函数中用指针才能改,不然只是改拷贝的值
结构体 结构体struct
type user struct {
name string
password string
}
//有user结构体了
a := user{name: "wang", password: "1024"}
var d user//结构体变量
//可以当函数参数
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) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
错误检测
func findUser(users []user, name string) (v *user, err error)在返回的数这可以添加个error。
字符串
a := "hello"
// 判断字符串 a 中是否包含字符串 "ll"
fmt.Println(strings.Contains(a, "ll")) // true
// 统计字符串 a 中字符串 "l" 出现的次数
fmt.Println(strings.Count(a, "l")) // 2
// 判断字符串 a 是否以 "he" 为前缀
fmt.Println(strings.HasPrefix(a, "he")) // true
// 判断字符串 a 是否以 "llo" 为后缀
fmt.Println(strings.HasSuffix(a, "llo")) // true
// 获取字符串 a 中字符串 "ll" 第一次出现的位置
fmt.Println(strings.Index(a, "ll")) // 2
// 使用 "-" 连接字符串数组
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
// 重复字符串 a 两次
fmt.Println(strings.Repeat(a, 2)) // hellohello
// 将字符串 a 中的 "e" 替换为 "E",替换所有匹配的字符
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo
// 将字符串 "a-b-c" 按照 "-" 分割成字符串数组
fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
// 将字符串 a 转换为小写
fmt.Println(strings.ToLower(a)) // hello
// 将字符串 a 转换为大写
fmt.Println(strings.ToUpper(a)) // HELLO
// 获取字符串 a 的长度
fmt.Println(len(a)) // 5
格式化
fmt.Printf("s=%v\n", s) // s=hello
fmt.Printf("n=%v\n", n) // n=123
fmt.Printf("p=%v\n", p) // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
保留两位小数还是%.2f这样
json
import引入"encoding/json"
// 使用 json.MarshalIndent 函数将结构体 a 编码为格式化的 JSON 字符串,指定缩进字符为空字符串和制表符 \t
buf, err = json.MarshalIndent(a, "", "\t")//buf存的就是json数据,err是是否错误的信息
// 使用 json.Unmarshal 函数将 buf 中的 JSON 数据解码到变量 b 中,并检查是否发生错误
err = json.Unmarshal(buf, &b)
if err!= nil {
// 如果发生错误,使用 panic 函数抛出异常,程序会停止执行
panic(err)
}
fmt.Printf("%#v\n", b)
时间time
now := time.Now()// 2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25
diff := t2.Sub(t)//t2和t做差求时间
fmt.Println(now.Unix()) // 1648738080
str转换
f, _ := strconv.ParseFloat("1.234", 64) 将字符串 `"1.234"` 转换为 float64 类型的数字。
fmt.Println(f) // 1.234
n, _ := strconv.ParseInt("111", 10, 64)将字符串 `"111"` 转换为 int64 类型的数字,并指定基数为 10。
fmt.Println(n) // 111
n, _ = strconv.ParseInt("0x1000", 0, 64)将字符串 `"0x1000"` 转换为 int64 类型的数字,并让函数自动推断基数。
fmt.Println(n) // 4096
n2, _ := strconv.Atoi("123")//Atoi把字符串转成整数
fmt.Println(n2) // 123
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
环境
需要import一下os和os/exec
// go run example/20-env/main.go a b c d
fmt.Println(os.Args) // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
// 打印命令行参数
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
// 打印环境变量 PATH 的值
fmt.Println(os.Setenv("AA", "BB"))
// 设置环境变量 AA 的值为 BB
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err!= nil {
panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1 localhost
// 在 /etc/hosts 文件中查找包含 127.0.0.1 的行,并打印结果