阅读 188

菜狗前端初识GO语言(2)

菜狗前端的go语言学习笔记(2)

写在文章前

上一篇的go语言开篇已经过去了数月,菜狗前端终于又开始继续学习了。和这个世界说了hello world之后,继续学习go语言的顺序编程。

变量

变量声明

下面的表能说明go 与 js变量声明的不同方式。

js go
布尔型 var isFool = true var isFool bool = true
整型 var i = 10 var v1 int = 10(go中包含int8, byte, int16, int,uint,uintptr)
浮点型 var i = 0.1 var pi float64 = 3.1415926,var zero = 0.0(无类型浮点常量), var size float32 = 3(size 为 3.0 ,常量的多重赋值)
复数 \ var i complex64 = 3.2 + 12i (complex64 & complex128)
字符串 var str = 'fdsdfs'; var str string = "sdfsdfs"
字符类型 \ var s rune
数组 var arr = [] var v3 [10]int
数组切片 \ var v4 []int
结构体 \ var v5 struct { f int }
指针 \ (this勉强算?) var v6 *int
对象 var obj = {key : 'value'} var v7 map[string] int (key 为string 类型,value 为int类型)
函数 function myFun() {} var v8 func (a int) int

除上述表格列出的之外,还有几个声明的特性:

  • 不需要使用分号作为结束符
  • 多个需要声明的变量放置在一起
var (
    v1 int
    v2 string
)
复制代码

变量初始化的三种不同方式

var v1 int = 10
var v2 = 10 // 编译器自动推导出类型
v3 := 10 // := 左侧的变量不能被声明后,否则会导致编译错误
复制代码

变量赋值

  • 普通赋值

    var v10 int
    v10 = 123
    复制代码
  • 多重赋值

    i,j = j,i // 交换两个变量的值 ; 不用再声明一个第三个变量来交换值
    复制代码

匿名变量

go语言允许通过使用多重返回和匿名变量来_来代替可能混淆代码阅读者视线的内容。

func GetName() (firstName,  lastNamem, nickName string) {
    return 'xiaoming','wang' ,'goudan'
}

// 只想获得nickname

_,_, nickName := GetName()

复制代码

常量

js 中 在es6以上使用const关键字来声明一个变量为常量,但是其实没有区分常量的类型。Go也是使用const 关键字来声明一个常量。并且Go语言和其他强类型的语言一样,区分 浮点类型,复数类型,布尔类型,字符串类型。但是与C++ 的区别在于,C++ 严格的区分了long类型的常量,和int类型的常量, Go 只要这个常量在相应类型的值域范围内就可以作为该类型的常量。

  • 定义
const pi float64 = 3.1415926
const a,b,c = 3,4,"foo"
const fushu = 3.2 + 12i // 复数类型
复制代码
  • 注意:
    • 常量定义的右边可以是一个再编译期运算的常量表达式
    • 常量的赋值是一个编译期行为,所以如果出现运行期才能得到的表达式,会造成编译错误。
    const Home = os.GetEnv("Home")
    复制代码

预定义常量

  • go语言中的预定义常量: true, false, iota
  • iota 是一个js中没有的概念,他在每一个const关键字出现时被重置为0,在下一个const出现之前,iota没出现一次,代表的数字会自动增加1.
const (  // iota 被设置为0
c0 = iota // c0 的值为0
c1 = iota // c1 的值为1
c2 = iota // c2 的值为2
)

const (  // iota 被设置为0
   a = 1 << iota  // 1<<1 = 1
   b = 1 << iota  // 1<<2 = 2
   c = 1 << iota  // 1<<3 = 4
复制代码
  • 若const 的赋值语句的表达式是一样的,那么可以省略后一个赋值表达式 。使用枚举可以简化赋值代码量
const (
    c0 = iota
    c1
    c2
)
复制代码

各种类型

布尔类型

var b bool = true

  • 注意: 布尔类型不能接受其他类型的赋值,不支持自动或者强制的类型转换,否则会有编译错误 (js中的各种隐式转换都不用考虑了,开心)

整型

  • int 和 int32 在go语言中是两种不同的类型。所以编译器没有办法实现自动类型转换
var value2 int32
value1 :=64 // value1 被编译器默认为int类型
value2 = value1 // 编译错误
value2 = int32(value1)
复制代码
  • 两个不同类型的整数是不能直接比较的,比如int8 和int就不行,但是各种整型变量都可以与字面常量比较
var i int32
var j int64

i,j = 1,2

if i == j {
    fmt.println("equal") // 编译报错
}
if i == 1 || j==2 {
    fmt.println("equal") // 通过
}
复制代码

浮点型

  • 浮点型包括:float32 和 float64
  • 浮点数不是一种精确的表达方式,所以不能用 === 直接哦按段是否相等。这个和那个经典的0.1 + 0.2 !== 0.3的原理是相似的。替代方案也是类似的, 我们采取截取到某个位数,只要这个位数内的数字是相等的我们就认为这两个数字是相等的。
import "math"

func isEqual(f1,f2, p float64) bool {
    return math.Abs(f1-f2) < p 
}
复制代码

字符串

字符串的初始化和声明: var str string str = "hello"

  • 字符串的内容可以用数组下标的方式获取,但是是只读的,不能被修改
  • 获取字符串长度的函数: len()
  • 打印字符串: js中使用的是控制台的console,go需要引入fmt库: fmt.printlb("hello")
  • go 只支持utf-8 以及Unicode编码,需要引入go-iconv 等其他的库
  • 字符串的链接: a + b
  • 字符串的遍历:
    • 字节数组的方式遍历
    str := "hello,世界"
    n := len(str)
    for i:= 0; i < n; i++ {
        ch := str[i]
        fmt.println(i,ch)
    }
    复制代码
    例子会输出的长度为13,因为中文字符在utf-8中占3个字节,而不是1个字节
    • unicode字符遍历:
    str := "hello,世界"
    for i, ch := range str{
        ch := str[i]
        fmt.println(i,ch)
    }
    复制代码
    长度为10.每个字符的类型都是rune

字符类型

byte代表的字符类型是uint8 的别名,代表utf-8 字符串单个字节的值 rune代表单个unicode字符

数组

js中数组更像一个百宝箱,他什么都能存,什么都能放,没有满的时候,随便添加。但是go就不是了,他指的是同一类型数据的结合。每个元素被叫做数组元素。

元素的读取

for i := 0; i < len(array); i++ {
    fmt.println("element:", i , "of array is", array[i])
}
for i, v := range array {
    fmt.println(i, v)
}
复制代码

值类型

在go语言中数组是一种值类型,而js中是引用类型,所以在go中做参数传递的时候都会产生一次复制动作,因此函数体中是无法修改传入的数组的内容。

那我们会想说,我们如果就想修改呢? go语言提供一个更灵活的类型: 数组切片

数组切片

数组切片可以抽象成为三个变量: 一个原声数组的指针,数组切片中的元素个数,数组切片已分配的存储空间

  • 创建数组切片
var myArray [10]int = [10] int{1,2,3,4,5,6,7,8,9,10} //数组
var mySlice []int =  myArray[:5] // 截取前五个元素的切片。
var mySlice []int = myArray[5: ] //从第5个元素开始的所有元素创建数组切片
复制代码
  • 直接创建make函数
myslice1 := make([]int, 5) //创建元素个数为5的数组切片
mySlice2 := make([]int, 5, 10)  // 创建元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间
mySlce3 := []int{1,2,3,4,5} //创建并初始化数组切片
复制代码
  • 元素的遍历

和数组类似,通过len()或者range来遍历

  • 动态增加元素

Go中的数组的长度是一定的,前端的小伙伴刚开始可能会不太适应,但是数组切片就和js中的数组很类似了,支持动态的增加删除元素。

数组切片中通过cap()来获取数组切片分配的空间大小,通过len()返回的是数组切片中所存储的元素个数。通俗来讲,就是你的房产证上写的就是cap()的数值,是包括公摊面积的建筑面积,而你实际住的是len的数值,就是使用面积。

如果想增加删除元素的话通过append函数:

mySlice = append(sourceSlice, 1,2,3)
// 第二个参数可以是元素,也可以是另一个切片的扩展
mySlice = append( sourceSlice, anotherSlice...)
复制代码

这个扩展运算符格外眼熟,但他不是领头羊,而是压轴的。

  • 内容复制: copy(target,source)
slice1 := []int{1,2,3,4,5}
slice2 := []int{5,4,3}

copy(slice2,slice1) // 复制slice1的前三个元素到slice2 ,因为slice2 只有3个位置
复制代码

map

map在js中是使用object来定义的,go中不需要使用任何库,用起来也很方便。

map的变量声明

var myMap map[string] PersonInfo
复制代码

map[string]表示的是key的类型为string,personInfo表示值的类型。

map的创建&赋值:make()

myMap = make(map[string] PersonInfo, 100)
myMap ["1234"] = PersonInfo("1","wangxiaomign")
复制代码

创建一个初始存储能力为100的map。并进行赋值。

元素的删除

delete 函数用于删除容器内的元素:delete(myMap, "1234")

如果1234这个键不存在的话,就什么都不会发生。但是如果传入的map变量的值为nil,则会抛出异常(panic)

元素的查找

通常go语言中获取一个值的常规做法:

  1. 声明并初始化一个变量为空
  2. 试图从map中获取相应的键值到该变量中
  3. 如果变量为空,则不包括这个变量。

因为有的库特别的刚,不存在直接抛出了异常,这可以说是十分暴躁了,导致开发者不得不使用try-catch来包裹。

go中提供了简单可行的方法:(这就是王者)

value,ok := myMap["1234"]
if ok {
    // ok 
}
复制代码

结语

今天的文章介绍了go中的基本类型,并简单的和js进行了一些比较,他们之中大部分是不太一样的,可以很明显的看出来强语言类型和弱语言类型的不同。下次会写一下流程控制,以及其他类型方式。

如果本文有什么错误,或者各位观众老爷有什么意见或者建议,都可以在评论区评论。:)

ps: 公司还在招聘,欢迎找我内推~

文章分类
阅读
文章标签