大家好,这是我给大家准备的新的一期专栏,专门讲golang,从入门到精通各种框架和中间件,工具类库,希望对go有兴趣的同学可以订阅此专栏。

---------------------------------------------------------------------------------------------------------------------------------

             上一篇文章中 【go从入门到精通】go包,内置类型和初始化顺序  偏重概念和知识,想必大家都对如何开始写代码已经开始蠢蠢欲动了,但是不要着急,基础知识扎实,能让你少走很多弯道。

基本数据类型

        正如前一篇的内容,go的基本数据类型和其他语言都差不多,我们可以先看看go是如何声明变量的。

标准声明

Go语言的变量声明格式为:

var 变量名 变量类型

变量声明以关键字var开头,变量类型放在变量的后面,行尾无需分号。 举个例子:

var str string

var i int32

var b bool

批量声明

每声明一个变量就需要写var关键字会比较繁琐,go语言中还支持批量变量声明:

var (

a string

b int

c bool

d float32

)

变量的初始化

Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil。

当然我们也可在声明变量的时候为其指定初始值。变量初始化的标准格式如下:

var 变量名 类型 = 表达式

举个例子:

    var a int32 = 1

 类型推导 有时候我们会将变量的类型省略,这个时候编译器会根据等号右边的值来推导变量的类型完成初始化。

    var str = "pprof.cn"     var i = 1 短变量声明 在函数内部,可以使用更简略的 := 方式声明并初始化变量。

package main

import (

"fmt"

)

func main() {

var i = 10

j := 100

fmt.Println(i,j)

}

匿名变量         在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量。 匿名变量用一个下划线_表示,例如我希望通过strconv。Atoi来将数字字符串转整型数字,由于这个函数有2个返回值,我只想用i接收最终的整型变量,用_来作为匿名变量,可以用下面的代码来实现:

package main

import (

"fmt"

"strconv"

)

func main() {

i,_:=strconv.Atoi("100")

fmt.Println(i)

}

            匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。 (在Lua等编程语言里,匿名变量也被叫做哑元变量。)

注意事项:

    函数外的每个语句都必须以关键字开始(var、const、func等)

    :=不能使用在函数外。

    _多用于占位,表示忽略值。

const常量的初始化

        相对于变量,常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。 常量的声明和变量声明非常类似,只是把var换成了const,常量在定义的时候必须赋值。

    const pi = 3.1415  

const同时声明多个常量时,如果省略了值则表示和上面一行的值相同。 例如:

    const (         n1 = 100         n2         n3     ) 上面示例中,常量n1、n2、n3的值都是100。

其他注意的

但是这里要注意的一些区别是:

      (1) 空指针值 nil :

package main

import (

"fmt"

)

func main(){

i := 0

p := &i

if p == nil {

fmt.Println("p is nil")

}

}

       (2)多行字符串的输出方式:

        Go语言中要定义一个多行字符串时,就必须使用反引号字符:

package main

import (

"fmt"

)

func main(){

s := `this

is

golang

program`

fmt.Println(s)

}

反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。

    

      (3)byte和rune类型

        组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来,如:

Go 语言的字符有以下两种:

    uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。

    rune类型,代表一个 UTF-8字符。

var a := '啊'

var b := 'b'

当需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32。 Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾

package main

import (

"fmt"

)

func disp() {

s := "hello 你好"

for i := 0; i < len(s); i++ { //byte

fmt.Printf("%v(%c) ", s[i], s[i])

}

fmt.Println("")

for _, r := range s { //rune

fmt.Printf("%v(%c) ", r, r)

}

}

func main() {

disp()

}

输出:

104(h) 101(e) 108(l) 108(l) 111(o) 32( ) 228(ä) 189(½) 160( ) 229(å) 165(¥) 189(½)  104(h) 101(e) 108(l) 108(l) 111(o) 32( ) 20320(你) 22909(好)

因为UTF8编码下一个中文汉字由3-4个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面输出中第一行的结果。

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。

我们有时候会有这样的需求,判断某个游戏玩家起的昵称不能超过10个汉字或者字符,那么我想你这个时候就知道用哪种方式了。

 (4)修改字符串

        要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。

package main

import (

"fmt"

)

func modstring1(s string) {

// 强制类型转换

bytes := []byte(s)

bytes[0] = 'H'

fmt.Println(string(bytes))

}

func modstring2(s string) {

// 强制类型转换

bytes := []rune(s)

bytes[0] = '你'

fmt.Println(string(bytes))

}

func main() {

s := "hello"

modstring1(s)

modstring2(s)

}

      (5)array数组    

            go的数组array是同一种数据类型的固定长度的序列。

           (1)如何定义一个数组呢?我们可以用: var 数组名   [长度],不过你要注意的是长度也是数组类型的一部分。              比如:

                var a [10]int 和var a [100]int是不同的类型    

               var arr0 [5]int = [5]int{1, 2, 3}  // 未初始化元素值为 0。 

               c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。

               var arr2 = [...]int{1, 2, 3, 4, 5, 6}  // 通过初始化值确定数组长度。           

            (2)数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1

          遍历数组有两种方式:

    for i := 0; i < len(a); i++ {     }     for index, v := range a {     }

             (3)访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic

         

package main

import "fmt"

func main() {

a := [3]int{1, 2, 3}

b := a[0]

c := a[6]

fmt.Println(b, c)

}

 运行时报错信息如下:

PS E:\project\go\hello> ./main.exe

panic: runtime error: index out of range [6] with length 3

goroutine 1 [running]:

main.main()

E:/project/go/hello/main.go:8 +0x1d

                         (4) 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。

       此时此刻,    一定有人想做下验证,于是写了如下代码:

package main

import "fmt"

func fun1(a []int) {

a[0] = 100

}

func main() {

a := []int{1, 2, 3}

fun1(a)

fmt.Println(a[0])

}

       这段代码似乎是想修改数组a的第一个元素的值,但是很不幸,你可能认为调用fun1之后,a的第一个元素的值仍然是1。

      为什么呢?  因为你传的不是数组,而且切片。 数组是指定了长度,且是值传递 而切片是没有指定长度,且是引用传递。所以你的代码改成这样就没有问题了:

package main

import "fmt"

func fun1(a [3]int) {

a[0] = 100

}

func main() {

a := [3]int{1, 2, 3}

fun1(a)

fmt.Println(a[0])

}

   (6)slice和map

       后边逐步针对这slIce,map,以及和数组的三者之间的比较差异来细细道来。 

类型转换

        Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。

强制类型转换的基本语法如下:

        目标类型(表达式) 其中,目标类型表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.

package main

import (

"fmt"

)

func main() {

i := int32(0)

var j int

j = i

fmt.Println(j)

}

 比如这段代码,简简单单,但是编译的时候报错:

cannot use i (variable of type int32) as int value in assignment

所以我们在把i赋值给j的时候,需要做个类型强制转换,j = int(i)

运算符

         go的常用的运算符用法和其他语言没有区别

      

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: