Go 语言入门指南:基础语法和常用特性解析|豆包MarsCode AI刷题

73 阅读6分钟

准备

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]intb := [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")删除了。

如果取不存在的键值对,会取出对应类型的零值。

{20AB05AB-CFE3-4D13-B6C9-1776D6AA5DAC}.png

输出: {E46DE8EE-450C-4BA1-B4A7-F08E6EAA53F5}.png

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 的行,并打印结果