1. go语言基础篇| 青训营笔记

128 阅读6分钟

这是我参与【第五届青训营】笔记创作活动的第1天

😻😻😻😻😻😻😻😻😻😻😻😻😻😻😻😻😻😻😻

写在前面: 本篇文章大概字数3000字,阅读时间6min。包括go介绍,环境配置、语言基础。其中语言基础方面,有关条件语句、循环语句等不再赘述,本人仅仅挑选一些对我来说go比较特别的语法进行分享。。。。。。

1.1 Go(Golang)简介

1.2 环境配置

1️⃣ 安装Golang

2️⃣ IDE的选择

推荐:

  • VSCode

    安装完成后,在扩展中搜索go插件然后安装

  • GoLand

1.3 Hello World

package main

import{
	"fmt"
}

func main(){
	fmt.Println("hello world")
}

1.4 Go语言基础—变量

变量类型: 字符串 整形 浮点型 布尔型

变量定义方法:

//1.字符串类型直接赋常量 , boolean型雷同

var a = "first"

var Boo = true

//2. var声明变量类型

var b, c int = 1, 3

//3. := 赋值
f := float32(e)

//4. const赋值

const s string = "constant"

const h = 500000

1.5 Go语言基础—切片

go语言切片是go语法的一大特点,与python语法类似,Go 语言切片是对数组的抽象。Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

  1. 定义切片:

    //1.声明一个未指定大小的数组来定义切片
    var identifier []type
    
    //2. 使用 make() 函数来创建切片
    var slice1 []type = make([]type, len)
    
    //3. 指定容量定义
    make([]T, length, capacity)
    
  2. 切片常见操作:

    /* 创建切片 */
    numbers := []int{0,1,2,3,4,5,6,7,8}
    
    /* 打印子切片从索引1(包含) 到索引4(不包含)*/
    fmt.Println("numbers[1:4] ==", numbers[1:4]) //[1 2 3]
    
    /* 默认下限为 0*/
    fmt.Println("numbers[:3] ==", numbers[:3])   //[0 1 2]
    
    /**
    如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。
    下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。
    */
    
    /* 向切片添加一个元素 */
    numbers = append(numbers, 1)   //[0,1,2,3,4,5,6,7,8,1]
    
    /* 同时添加多个元素 */
    numbers = append(numbers, 2,3,4)  //[0,1,2,3,4,5,6,7,8,1,2,3,4]
    

1.6 Go语言基础—函数

由于本人常用语言为java,因此我认为go语言的函数也是非常与众不同的一点,Golang里面的函数原生支持返回多个值。在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息。

package main

import "fmt"

func exists(m map[string]string, k string)(v string, ok bool){
	v, ok = m[k]
	return v, ok
}

1.7 Go语言基础 — 结构体方法

在Golang里面可以为结构体去定义一些方法。会有点类似于其他语言里面的类成员函数,

其中我认为,方法的本质是函数,但是方法和函数又具有不同点。

Go 方法是作用在接收者(receiver)上的一个函数,接收者是某种类型的变量。因此方法是一种特殊类型的函数。

接收者类型可以是(几乎)任何类型,不仅仅是结构体类型:任何类型都可以有方法,甚至可以是函数类型,可以是 int、bool、string 或数组的别名类型。

方法的格式:

func (recv receiver_type) methodName(parameter_list) (return_value_list) { … } func (_ receiver_type) methodName(parameter_list) (return_value_list) { … }

函数与方法的区别:

  • 函数将变量作为参数:Function1(recv)
  • 方法在变量上被调用:recv.Method1()

如以下例子中

package main
import "fmt"
type user  struct {
	name string
	password string
}
func (u user) checkPassword( password string) bool {
	return u.password e= 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
}

我们将checkPassword与resetPassword两个普通函数修改为了结构体方法,这样的话用户就可以通过a.checkPassword(”xxx”)的方式去调用

同时在实现结构体方法的时候也有两种方式

  • 带指针方式
    • 该方法可以对结构体本身进行修改
  • 不带指针方式
    • 操作的只是结构体的一个拷贝,无法对原结构体进行修改

1.8 Go语言基础 — 错误处理

相比于其他语言而言,Go 语言通过内置的错误接口提供了非常简单的错误处理机制。error类型是一个接口类型,它的定义如下:

type error interface {
    Error() string
}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
    // 实现
}

在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,如下所示

result, err:= Sqrt(-1)

if err != nil {
   fmt.Println(err)
}

1.9 Go语言基础 — json处理

Go留给我的一个更深的印象便是它的json处理方式,go中的json操作非常的方便,对于一个已有的结构体,我们可以什么都不做,只要保证每个字段的第一个字母是大写,也就是是公开字段。那么这个结构体就能用JSON.marshaler 去序列化,变成一个JSON 的字符串。

序列化之后的字符串也能够用JSON.unmarshaler 去反序列化到一个空的变量里面。 这样默认序列化出来的字符电的话,它的风格是大写字母开头,而不是下划线,我们可以在后面用 json tag 等语法来去修改输出 JSON 结果里面的字段名

使用go的json处理方法如下所示

type userInfo struct{
	Name string
	Age int `json : "age"`
	Hobby []string
}

func main() {
	a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
	buf, err := json.Marshal(a)
	if err != nil {
		panic(err)
	}
	fmt.Println(buf)         // [123 34 78 97...]
	fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}

	buf, err = json.MarshalIndent(a, "", "\t")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(buf))

	var b userInfo
	err = json.Unmarshal(buf, &b)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}

小结

经过一天的青训,让我对go的认知更加加深了,go的高效是肉眼可见的,拿最简单的例子来说,我们平时在leetcode进行刷题时,对于相同逻辑的代码,java 与 go的运行内存消耗竟然相差10倍之多,这也解释了为什么go能够去做那些容器化技术,去把一些服务做的那么轻量级。相信随着时代的变迁,go的生态也能做的够越来越好吧!!