Golang语言学习笔记(打卡✏️第二天)|Go主题月

390 阅读6分钟

关于Golang的九大特性深入理解笔记

1.自动垃圾回收

在语言层次进行自动垃圾回收,相比自己写来说能避免有所遗漏而导致内存泄露。

总结: 我们只需要知道它是有自动垃圾回收机制来防止内存泄漏就可以了。

2.更丰富的内置类型

  • 内置基础类型包括 整型 浮点型 字符串类型
  • 内置高级类型包括 数组 字典类型(map) 切片slice 序列数组(最常用)

这些类型都是什么样子?

  • 整型 : 有符号(负号) 【int8 int16 int32 int64】定义方式: var a int32或者var a int64 = 1

无符号(没负号)【uint 基于平台位数8 uint16 uint32 uint64】定义方式:var b uint32

int/uint (依赖于不同平台下的实现)可以是 int32 或者是 int64

  • 浮点型 : float32 IEEE-754 32位浮点型数 (IEEE-754指的是IEEE二进制浮点数算术标准)

float64 IEEE-754 64位浮点型数

下边的2个复数类型,complex64和complex128,分别由float32和float64组成。

实部与虚部:他们是数学名词"复数"中的一个概念,把形如z=x+iy(x,y是任意实数),y称为复数z的虚部的数称为复数,而x称为实部,y称为虚部,i称为虚数单位。

complex64 32 位实数和虚数

complex128 64 位实数和虚数

var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y)                 // "(-5+10i)"  由(1+2i)*(3+4i)得出 3+10i+8i² 根据下方定义得出3+10i-8=-5+10i
/*如果一个浮点数的字面量后面跟着一个i,例如3.141592i或2i,那么它将变成一个复数的虚部,这个复数的实部是0:*/ 
fmt.Println(real(x*y))           // "-5"  获取实部函数
fmt.Println(imag(x*y))           // "10"  获取虚部函数

具体的实际应用场景我还没想好,谁如果能有什么指导建议可以私信或者评论我

  • 字符串类型 1.go中字符串一旦赋值了,就不能修改字符串,是不可变的。

2.字符串拼接用"+"。

3.字符串的双引号表示,会识别转义字符.用反引号(``) 表示的时候,不识别转义字符,原生形式输出,包括换行和特殊字符,可以实现防止攻击

  • 字典类型 格式:temp_map := map[string]int{"a": 1, "b": 2, "c": 3} 其中,“string”为键的类型,而“int”则代表元素(或称值)的类型。
  • 数组类型 这里和PHP不太一样,下边是声明方式
var a [5]byte //长度为5,每个元素为一个字节
var b [2*N] struct { x, y int5 } //复杂类型数组
var c [5]*int // 指针数组
var d [2][3]int //二维数组
var e [2][3][4]int //等同于[2]([3]([4]int))

参照例子运行结果:

package main

import(
"fmt"
)

func main(){
    var arr1 [5]int
    arr2 := [5]int{1, 2, 3}   //指定长度为3,并赋3个初始值
    arr3 := [5]int{1, 2, 3}         //指定长度为5,对前3个元素进行赋值,其他元素为零值
    arr4 := [5]int{4: 1}            //指定长度为5,对第5个元素赋值
    arr5 := [...]int{1, 2, 3, 4, 5} //不指定长度,对数组赋以5个值
    arr6 := [...]int{8: 1}          //不指定长度,对第9个元素(下标为8)赋值1
    fmt.Println(arr1, arr2, arr3, arr4, arr5, arr6)
}
输出结果:
[0 0 0 0 0] [1 2 3 4 5] [1 2 3 0 0] [0 0 0 0 1] [1 2 3 4 5] [0 0 0 0 0 0 0 0 1]
  • 切片类型 基于数组,为开发提供便利性;而go的数组是不太灵活的。
//直接定义一个切片
letters := []string{"a", "b", "c", "d"}//定义切片时不用定义长度
//内置的make关键字定义切片
func make([]T, len, cap) []T
//T表示切片中元素的类型。make函数接受元素类型,长度和容量(可选)作为传入参数。当被调用时,make分配一个数组,并且返回一个指向该数组的切片。

数组和切片这块需要专门花时间把案例代码都去亲自敲一遍,熟悉其用法(安排在第二周)

  • 其它 包含结构化类型(struct)、Channel 类型、函数类型、接口类型(interface)...

3.语言交互性

主要是同C语言的交互,通过工具Cgo工具实现,如下import "C"前的注释内容是有意义的,通过C.* 来调用具体的函数

package main
/*
#include <stdio.h>
*/
import "C"
import "unsafe"
func main() {
    cstr := C.CString("Hello, world")
    C.puts(cstr)
    C.free(unsafe.Pointer(cstr))
}

4.反射

定义:Golang提供了一种机制,在编译时不知道类型的情况下,可更新变量、运行时查看值、调用方法以及直接对他们的布局进行操作的机制,称为反射。 主要包含两种类型

类型说明
reflect.ValueOf()获取输入参数接口中的数据的值,如果为空则返回0 <- 注意是0
reflect.TypeOf()动态获取输入参数接口中的值的类型,如果为空则返回nil <- 注意是nil
package main

import (
	"fmt"
	"reflect"
)

func main() {
	var name string = "字符串值"
	// TypeOf会返回数据的类型 
	Type := reflect.TypeOf(name)
	// valueOf返回数据的的值
	value := reflect.ValueOf(name)
	fmt.Println("type: ", Type)
	fmt.Println("value: ", value)
}

输出结果:
type:  string
value:  字符串值

5.并发编程

很重要的一点,不同于传统的多进程或多线程,golang的并发执行单元是一种称为goroutine的协程。

golang中实现协程间通讯有两种:

1)共享内存型,即使用全局变量+mutex锁来实现数据共享;

2)消息传递型,即使用一种独有的channel机制进行异步通讯。

这点要重点去研究的地方(安排在第二周)

6.类型和接口

Go语言没有很复杂的面向对象的概念,即没有继承和重载,但是以不同形式实现,具体的接下来了解(安排在第二周)

7.匿名函数和闭包

匿名函数是指不需要定义函数名。闭包是指定义在函数内部的变量,不被外部所获取。

8.错误处理

golang不支持try...catch

golang异常处理方式是:

普通异常:被调用方返回error对象,调用方判断error对象。

严重异常:指的是中断性panic(比如除0),使用defer...recover...panic机制来捕获处理。严重异常一般由golang内部自动抛出,不需要用户主动抛出,避免传统try...catch写得到处都是的情况。当然,用户也可以使用panic('xxxx')主动抛出,只是这样就使这一套机制退化成结构化异常机制了。

综上,正常情况要我们不需要去专门些异常抛出的语句,其会自动进行错误处理。

9.函数多返回值

python有多返回值功能,其他语言基本上没有;

package main

import "fmt"
//多返回值
func getNumber(x int,y int) (sum int, product int) {
    return x+y, x*y
}
func main() {
    // 获取函数的两个返回值
    a, b := getNumber(2,3)
    fmt.Println(a, b)
    // 如果只需要其中几个,可以使用下划线(_)来忽略其他的返回值
    _, sum := getNumber(2,3)
    fmt.Println(sum)
}

运行结果: 图片.png