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

106 阅读4分钟

Go 语言基础语法-下

函数

package main

import "fmt"

func add(a int, b int) int {
	return a + 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]
	return v, ok
}

func main() {

	res := add(1, 2)
	fmt.Println(res) // 3

	v, ok := exists(map[string]string{"a": "A"}, "a")
	fmt.Println(v, ok)

}

  • 需要注意,golang 一大特点就是 变量类型后置,变量名在前 。体现在函数的创建也是一样,先写函数名,然后紧跟着是括号里传参,完了之后才把函数的返回值类型加上,如果不加的话 golang 默认是无返回值,只进行函数体里的操作,比较省事儿。
  • 可以看代码里的 exists 函数,返回值类型是 (v string, ok bool) ,这和我们之前学的很不一样,着重解释一下 :意思是 exists 函数的返回值有两个,第一个是 string 类型的,第二个是bool 类型的。第一个就是我们平时都用的需要的返回值,第二个 bool 类型的值通常作为返回目标是否存在的标志。

指针

相比于 C/C++ 里的指针,golang 里的指针作用非常有限,指针的一个主要用途就是对传入的参数进行修改 。学过 C 语言的指针就会知道,我们传一个参数到函数里,传的是这个参数的值,相当于是复制过去的,在另一个函数里对它进行修改对这个参数本身并没有影响,所以加上指针之后,就变成了传引用,将参数在内存的地址传过去,那么此时再进行修改,参数的值就会改变了。

可以参考示例代码:

package main

import "fmt"

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

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

func main() {
	n := 5
	add2(n)
	fmt.Println(n)	// 5
	add2ptr(&n)
	fmt.Println(n)  // 7
}

ps : 还要注意传引用的时候要有取地址符 &


结构体

type user struct {
	name     string
	password string
}

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

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

func main() {

	a := user{name: "wang", password: "1024"}
	b := user{"wang", "1024"}
	c := user{name: "wang"}
	c.password = "1024"
	var d user
	d.name = "wang"
	d.password = "1024"

	fmt.Println(a, b, c, d)                 // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
	fmt.Println(checkPassword(a, "haha"))   // false
	fmt.Println(checkPassword2(&a, "haha")) // false
}

  • 和 C 语言一样的结构体。初始化有不同的方式,如果初始化的时候显式地加上了字段的名称的话,那么就可以不完全赋值,比如a是给每个字段都赋值了,而c就只给部分赋值了,对于未初始化的默认给初值 0,字符串就是空串;如果是隐式的,那么就如 b 一样了。
  • 如代码中的 d,可以用 . 来使用结构体的值,这对于学过 C 语言的同学来说肯定是不陌生的
  • 作为参数传入时 ,肯定是也区分带星号不带星号(就是用不用指针的意思)。那么不带星号就是修改参数的值不对本体有影响。

结构体方法

type user struct {
	name     string
	password string
}
func (u user) checkPassword(password string) bool {
	return u.password == password
}
func (u *user) resetPassword(password string) {
	u.password = password
}

func main() {
	a := user{
		name:     "wang",
		password: "1024",
	}
	a.resetPassword("2048")
	fmt.Println(a.checkPassword("2048")) 	// true
}

  • 参考上一part 的结构体,结构体方法其实就是把本来在参数列表里的结构体变量往前提,提到函数名前边,这样做的好处我们可以看倒数第二行 a.resetPassword("2048") ,我们就可以通过 变量名.方法名 的方式来调用函数了。

字符串操作

字符串常用操作

介绍了一些常用的golang 处理字符串的方法

func main() {
	a := "hello"
	// 判断前一个字符串里是否有后一个字符串
	fmt.Println(strings.Contains(a, "ll")) // true
	// 字符串基数
	fmt.Println(strings.Count(a, "l")) // 2
	fmt.Println(strings.HasPrefix(a, "he")) // true
	fmt.Println(strings.HasSuffix(a, "llo")) // true
	// 查找某个字符串的位置
	fmt.Println(strings.Index(a, "ll")) // 2
	// 连接多个字符串
	fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
	// 重复多个字符串
	fmt.Println(strings.Repeat(a, 2)) // hellohello
	fmt.Println(strings.Replace(a, "e", "E", -1)) //hEllo
	fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
	fmt.Println(strings.ToLower(a)) // hello
	fmt.Println(strings.ToUpper(a)) // HELLO
	fmt.Println(len(a)) // 5
}

字符串的格式化

使用 fmt.Printf() 方法进行格式化输出,和 C/C++ 的 printf() 及 java 的 String.format() 基本一样用法。
  • 不过需要区别且 体现Go 语言的简洁性的一大特点 在于:无论什么数据类型,都可以用 %v 来输出,不像C 语言里边 %c 代表字符型、%d 代表整型什么什么的,一个 %v 就是万能的。
  • 如果想要更详细的输出信息,可以使用 %+v%#v ,后者比前者更详细,这里就不过多演示。

JSON处理

  • 很简单,对于一个已有的结构体,保证每个字段的首字母都大写 (也就是表示在 golang里这属于公开字段了),就可以用 json.Marshal() 方法去事例化,这样就会变成一个数组(全是16进制数字),打印的时候强制转换类型为 string 就能打印出字符串了。