当前位置:澳门新萄京网址 > 澳门新萄京网址 > 常量和数据类型

常量和数据类型

文章作者:澳门新萄京网址 上传时间:2019-11-25

文章由笔者马志国在网易的原创,若转发请于显然处标记出处:

2.1 变量

变量是对一块内存空间的命名,程序能够因而定义三个变量来报名一块内部存款和储蓄器空间。然后能够通过引用变量名来使用那块存款和储蓄空间。

 图片 1

2.1.1 变量命名

Go语言中的变量名、常量名、类型名、函数名和包名等具有的命名和C语言相像都遵从那样叁个轻巧易行的命名准绳:叁个名字必须以四个假名或下划线起先,后边能够跟任性数量的字母、数字或下划线。对于字母区分朗朗上口写,举个例子:name和Name是五个例外的名字。

取名不能够与根本字相符,Go语言提供了二十多个首要字,只好在一定的语法中选用。

23个重视字

break

default

func

interface

select

case

defer

go

map

struct

chan

else

goto

package

switch

const

fallthrough

if

range

type

continue

for

import

return

var

 

除此以外,Go语言还会有大概30多少个预订义的名字,主要用来内建的常量、类型和函数。那个名字未为不可缺乏字,可以重新定义和动用,即使在部分特殊现象中重复定义是有含义的,但建议尽量不要再次定义,以形成语义混乱难点。

内建常量

true false iota nil

内建品种

int int8 int16 int32 int64

uint uint8 uint16 uint32 uint64 uintptr

float32 float64 complex128 complex64

bool byte rune string error

内建函数

make len cap new append copy close delete

complex real imag

panic recover

 

2.1.2 变量声明

1 平日宣称格式

动用var能够创制叁个特定项目标变量。变量评释的平常语法如下:

var 变量名 类型 =  表达式

内部“类型”或“=表达式”八个部分能够轻巧此中的三个。假诺轻松的是类型音讯,那么将依照开头化表明式来演绎变量的门类。假如表明式省略,将用零值最早化该变量。

var i int = 1

var j int   //j的值初始化为0

var k = 10  // k的类型自动推导

借使贰个名字在函数内部定义,那么它只好在函数内部选择,如若在函数外界定义,那么在现阶段包的享有文件都得以采访。名字首字母的尺寸写决定了它在包外的可以知道性,首字母大写在包外可以访谈。包自己的名字常常总是用小写字母。

在包等级证明的变量会在main入口函数推行在此以前造成开首化,局部变量就要宣称语句被施行的时候做到初阶化。若无出示初叶化,那么将用零值初阶化该变量。四个变量申明后不曾行使也会孳生编写翻译错误。

2 简短变量注脚

“名字 := 表明式”,变量的等级次序依照表明式自动推导。由于接纳简单利落,被周围用于一大半的部分变量的扬言和开始化。注意,简短变量证明无法用来包级其余变量申明。

i := 100

 

3 几个变量注脚

var i, j, k int = 1, 2, 3

var m, n int

var a, b, c = 1, 2, 3

d, e, f := 1, 2, 3

name, age := "张三", 20

也可以那样写:

var (

     name string

     age  int

)

 

2.1.3 赋值

1 简单赋值

赋值语句是修正一个变量的值,最简便的赋值”变量名= 新值的表达式”

var i int

i = 1      //简单赋值

 

2复合赋值运算符

特定的二元算术运算符和赋值语句的复合操作有三个简短的样式

var i int

i = i + 1

i += 1    //与i = i + 1等价

 

数值变量也能够支撑++依次增加和--依次减少语句。注意它是话语,不是表明式,所以x=i++那样的表明式是荒诞的。

3多种赋值

多种赋值允许同期更新多少个变量的值。在赋值以前,赋值语句左侧的保有表达式会先举行求值,然后再统意气风发更新侧面前蒙受应的变量的值。那样在做八个数值调换时,无需引入第八个变量了。

x,y=y,x

4 _标识符

稍稍表达式会发生两个值,比方调用多少个有八个再次回到值的函数。能够利用下划线空白标识符_来抛弃不要求的值。

_, err := io.Copy(dst, src)//丢弃字节数

 

2.2 常量

在Go语言中,常量是指编写翻译时期就已知且不可退换的值。常量的地下类型都是幼功项目,包涵整型、浮点型、复数型、布尔类型和字符串类型等。

2.2.1 字面常量

所谓字面常量,是指程序中硬编码的常量,如:

25

3.14159

2+3i

true

"hello"

在其他语言中,常量平常有一定的连串,Go语言的字面常量是无类型的。只要那个常量在相应品种的值域范围内,就足以充作该类型的常量。比方,25足以赋值给int、 uint、int32、int64、float32、float64、complex64、complex128等类型的变量。

2.2.2 常量注解

应用const来声称常量,能够给常量贰个和好的名字比方:

const pi = 3.1415926

也能够批量宣称:

const (

     e = 2.7182818

     pi = 3.1415926

)

三个常量的扬言也得以界定品种,但不是少不了的。若无显示钦赐项目,那么它与字面量同样,是无类型常量。常量定义的右值也得以是三个在编写翻译期运算的常量表明式,举个例子:

const i = 1 << 3 //右值是常量表达式

假诺是批量宣称的常量,除第叁个外别的的常量的入手的初阶化表明式都足以省略,暗许使用前边常量的早先化表明式写法。举例:

const (

        a = 1

        b

        c = 2

        d

        e

    )

    fmt.Println(a, b, c, d, e)

打印结果:1 1 2 2 2

2.2.3 iota常量生成器

Go语言预订义的常量有:true、false和iota,当中iota相比较特出。常量申明可以动用iota常量生成器初步化,它用来生成一组以经常法则最初化的常量,可是不要每行都写三回起初化表明式。在二个const评释语句中,在率先个评释的常量所在的行,iota将会被置为0,然后在每叁个有常量注解的行加后生可畏。上边是来源于time包的例子。这种定义法在Go语言中见惯不惊用于定义枚举值。

type weekday int

const(

    Sunday weekday iota   //0

    Monday                //1   

    Tuesday               //2

    Wednesday             //3

    Thursday              //4

    Friday                //5 

    Saturday              //6

)

咱俩也足以在错综相连的常量表明式中运用iota,例如上面每种常量都是1024的幂。

const (

    _ = 1 << (10 * iota)

    KiB

    MiB

    GiB

    TiB

)

fmt.Println(KiB, MiB, GiB, TiB)

打印结果:1024 1048576 1073741824 1099511627776

小结:var 证明变量,const申明常量。注解时能够带项目。也能够不带项目,通过右估算。

2.3 数据类型

Go语言将数据类型分为四类:底蕴项目、复合类型、援引类型和接口类型。

  1. 基本数据类型:数值、字符串和布尔型。
  2. 复合数据类型:数组和结构体。
  3. 引用类型:指针、切成丝、字典、函数和通道。
  4. 接口类型。

2.3.1 整数

1 整数类型

Go语言的数值类型包蕴了二种不一致长短的平头、浮点数和复数。每一个数值类型都决定了相应的取值范围和是不是协理正负号。

 

类型

长度(字节)

取值范围

int8

1

(0~255)

uint8

1

(-128~127)

int16

2

(0~65535)

uint16

2

(-32768~32767)

int32

4

(-2147483648~2147483647)

uint32

4

(0~4294967295)

int64

8

(-9223372036854775808~9223372036854775807)

uint64

8

(0~18446744073709551615)

int

4或8

与机器字长和编译器都有关系

uint

4或8

与机器字长和编译器都有关系

uintptr

4或8

32平台4个字节,64位平台8个字节,底层编程才需要

byte

1

与uint8等价,通常表示一个unicode字符编码

rune

4

与int32等价,一般强调是一个原始数据而不是一个小整数。在一个字符串中,表示一个字符对应utf8的码点。

 

2 运算符

Go语言提供了丰盛的内置运算符,包罗算术运算符、相比较运算符、逻辑运算符、位运算符、赋值运算符和别的运算符等。

算术运算符:

运算符

描述

+

-

*

/

%

模运算(求余数)

++

自增

--

自减

 

在Go语言中,%取模运算符的暗记和被取模的暗记总是同样的,由此5%3和5%-3的结果都以2。除法运算符的结果则凭仗于操作数是不是全为整数,比如5.0/4.0的结果是1.25,然而7/4的结果为1,去掉小数部分,并非四舍五入。

关系(比较)运算符:

八个风度翩翩律的板寸类型能够利用上边包车型客车二元关系运算符举办比较,相比较表达式的结果是布尔类型。

运算符

描述

==

相等

!=

不等

<

小于

<=

小于或等于

>

大于

>=

大于或等于

 

 

逻辑运算

运算符

描述

!

&&

||

 

位运算:

前4个操作运算符并不区分是有记号照旧无符号数:

运算符

描述

&

位与and (左侧和右侧都为1,则为1;否则为0)

|

位或 or(左侧或右侧只要有一个为1,结果为1;都为0结果才为0)

^

位异或 xor (相同为0,不同为1)

&^

位清空and not(右侧是0,左侧数不变;右侧是1,则左侧数清零)

<<

左移

>>

右移

位运算的事例:

X=2,y=15

二进制结果

十进制结果

0000 0010 & 0000 1111

0000 0010

 2

0000 0010 | 0000 1111

0000 1111

15

0000 0010 ^ 0000 1111

0000 1101

13

0000 0010 &^ 0000 1111

0000 0000

0

0000 0010<<3  

0001 0000

16

0000 0010>>1

0000 0001

1

 

运算符优先级:

 

 

2.3.2 浮点数

浮点数用于表示富含小数点的数额。Go语言提供了三种精度的浮点数,float32和float64。float32与float64之间供给强制转变。强制转变的情势T(V),T为要改换的对象项目,V须要转移的变量。

1 浮点数表示

var f1 float32

f1 = 10

f2 := 12.0 //带小数点的自动推导为float64

f2 = float64(f1) //需强制转换

 

2 浮点数比较

因为浮点数不是生龙活虎种标准的表明形式,所以不可能像整型那样直接用==相比较。推荐的主意如下,引进math包,总结三个数值之差的相对化值,如果那些结果充足小,大家就觉着那多个数值是格外的。至于那些数小到哪些水平定义为相等,程序猿能够依附项目供给和睦定义。

import  "math"

func IsEqual(f1, f2, p float64) bool {

    return math.Abs(f1-f2) < p

}

 

3 科学计数法

把三个数表示成a(1≤a<10,n为整数卡塔 尔(阿拉伯语:قطر‎与10的幂相乘的格局,这种记数法叫做科学记数法。举个例子:1989=1.99×10^3。计算器或计算机表达10的幂是相通是用E或e,也便是1.99E3=一九九零。

f1 := 1.99e+3   //1990

f2 := 1.99e-3   //0.00199

 

2.3.3 复数

Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64三种浮点数精度。内建函数和自然的书写格局。

x := complex(1, 2) //内建函数

y := 1 + 2i     //自然书写

// real返回实部,imag返回虚部

fmt.Println(x, y, real(x), imag(x), real(y), imag(y))

打印结果:(1+2i) (1+2i) 1 2 1 2

2.3.4 布尔型

一个布尔类型的值独有二种:true和false。布尔值不会隐式调换为数值0或1。布尔值能够和&&、||操作符结合,何况或许会有窒碍行为。假若运算符右边已经足以明确整个布尔表明式的值,那么右侧的表达式将不再求值。

var s string

//s = "mazhiguo"

if s != "" && s[0] == 'm' {

   fmt.Println("OK")

else {

   fmt.Println("error")

}

2.3.5 字符串

1 字符串常用操作

在Go语言中字符串也是生机勃勃种为主项目。三个字符串是叁个不可修改的字节连串。常用的字符串操作如下表所示:

运算

含义

备注

s1+s2

字符串连接

 

len(s)

字符串长度

字符串中的字节数,不是字符数

s[i]

取字符

索引i不能越界

s[i:j]

取子字符串

左闭右开,包含s[i],不包含s[j]。子字符串是一个新的字符串。

i,j都可能被忽略,忽略时,从0开始,最后一个字符结束。

 

s := "hello " + "world"

fmt.Println(len(s))// 11

fmt.Println(s[0], s[len(s)-1])//104 100 (h 和 d)

fmt.Println(s[1:4])//"ell"

fmt.Println(s[:5])//"hello"

fmt.Println(s[6:])//"world"

fmt.Println(s[:])//"hello world"

2 字符串值不可变

字符串的值是不可变的:四个字符串满含的字节系列永久不会被转移,当然大家得以给两个字符串变量分配二个新字符串值。

s := "hello world"

s[0] = "H"  //这是错误演示,字符串序列不能修改

s = "Hello" //给字符串变量s重新赋值

3 字符串遍历

字符串遍历帮忙以字节的艺术遍历和以字符的艺术遍历。

s := "hello 世界"

n := len(s)

//以字节的方式遍历

for i := 0; i < n; i++ {

  fmt.Println(i, s[i])

}

//以字符的方式遍历

for i, ch := range s {

  fmt.Println(i, ch)

}

 

打印结果:

0 104

1 101

2 108

3 108

4 111

5 32

6 228

7 184

8 150

9 231

10 149

11 140

0 104

1 101

2 108

3 108

4 111

5 32

6 19990

9 30028

 

4转义队列

在两个双引号包含的字符串字票面价值中,能够用反斜杠起先的转义系列插入任性的数目。

广泛的ASCII调控代码的转义形式:

 

 

 

a

响铃

b

退格

f

换页

n

换行

r

回车

t

水平制表符

v

垂直制表符

单引号

双引号

\

反斜杠

 

 

5原生字符串字面值

原生的字符串字面值,用` `替代双引号。可用以编写正则表达式。常用来HTML模板、JSON面值、命令提醒消息甚至须要扩充到多行的现象。

tips := `请按要求执行以下操作:

 1 输入参数

 2 计算

 3 打印结果`

fmt.Println(tips)

 

6 UTF8编码

UTF8编码是一种字符编码,使用1到4个字节表示三个字符。ASCII部分字符只利用1个字节,常用字符部分应用2或3个字节。变长的编码无法直接通过索引来访谈第n个字符。

Go语言的源文件采纳UTF8编码,unicode/utf8包提供提供了用于rune字符种类的UTF8编码和平解决码成效。如果关怀每一种unicode字符,能够行使UTF8解码器。unicode/utf8席卷提供了该作用。

s := "hello 世界"

fmt.Println(len(s))    //12

fmt.Println(utf8.RuneCountInString(s))//8

将二个整数型调换为字符串意思是生成以只含有对应unicode编码字符的UFT8字符串,要是对应的编码的字符无效,将用‘uFfFD’无效字符作为替换:

fmt.Println(string(65))      //"A"

fmt.Println(string(0x4eac))  //"京"

fmt.Println(string(12345678)) //无效字符

 

string 接受到[]rune的类型转换,能够将四个UTF8编码的字符串解码为unicode字符串类别:

s := "世界"

fmt.Printf("%xn", s) //e4b896e7958c,utf8编码

r := []rune(s)

fmt.Printf("%xn", r) //[4e16 754c],unicode编码

 

 

比方说"汉"字的Unicode编码是6C49。6C49在0800-FFFF之间,所以要用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 1100 0100 1001,将那些比特流按三字节模板的支行方法分为0110 110001 001001,依次取代模板中的x,获得:1110-0110 10-110001 10-001001,即E6 B1 89,那正是其UTF8的编码。

s := "汉"

fmt.Printf(" %xn", s) // e6b189,UTF8编码

r := []rune(s)

fmt.Printf("%xn", r)  //[6c49],unicode编码

unicode相当于字符编码,即字典。utf8、uft16是如何以字节的不二秘籍存款和储蓄这些编码。字符串可正如、可遍历、不可更正。

2.4指针

2.4.1 指针概念

指南针是一个项目,该品种的变量称为指针变量。指针变量存款和储蓄八个变量的地点。它不相同于平常的变量,日常变量寄放的是数码自个儿,而指针变量寄存的是数额的地点。

 图片 2

2.4.2 申明指针变量

声明指针变量的貌似方式如下:

var 变量名 *类型

例如:

var ip *int     //指向int类型的变量

var fp *float32 //指向float32类型的变量

var ptr [MAX]*int;//指向数组的指针

 

指南针操作注意事项:

  1. 默认值 nil,没有 NULL 常量。
  2. 操作符 "&" 取变量地址, "*" 通过过指针访谈目的对象。
    不⽀持指针运算,不⽀持 "->" 运算符,直接⽤ "." 访问指标成员
  3. 无法对指针做加减法等运算
  4. 不设有函数的指针

package main

 

import "fmt"

 

type Student struct {

    Name string

    Age  int

}

 

func main() {

    a := 10

    b := 12.5

    var pa *int = &a

    var pb *float64 = &b

    //1 打印变量的值

    fmt.Printf("%v,%vn", a, b)

    fmt.Printf("%v,%vn", *pa, *pb)

    // 2 打印变量的地址

    fmt.Printf("%v,%vn", &a, &b)

    fmt.Printf("%v,%vn", pa, pb)

    // 3 指针默认值为nil

    var pc *int

    fmt.Printf("%v,n", pc)

    // 4 通过指针访问对象成员

    ps := &Student{"张三", 18}

    fmt.Println(ps.Name, ps.Age)

}

2.4.3数组指针和指针数组

数组指针是只一个指针变量保存的是数组的地点。指针数组,是指数组的各样成分都以指针类型。

package main

 

import "fmt"

 

func main() {

 

    var ptr *[3]int //数组指针

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

    ptr = &arr //保存了数组的地址

    fmt.Println(*ptr)

 

    var ptr2 [3]*int //指针数组,每一个元素都是指针

    a, b, c := 10, 20, 30

    ptr2[0] = &a

    ptr2[1] = &b

    ptr2[2] = &c

    fmt.Println(ptr2) //ptr2数组中的3个指针分别保存了a,b,c的地址

 

}

// 打印结果:

[1 2 3]

[0xc04200a2c8 0xc04200a2e0 0xc04200a2e8]

 

 

2.4.4 二级指针(多级指针)

二级指针保存一流指针变量之处。

package main

 

import "fmt"

 

func main() {

 

    var a int = 100

    var pa *int = &a

    var ppa **int = &pa

 

    //打印a的值

    fmt.Printf("%v,%v,%vn", a, *pa, **ppa)

    //打印a的地址

    fmt.Printf("%v,%v,%v", &a, pa, *ppa)

 

}

//打印结果:

100,100,100

0xc0420401d0,0xc0420401d0,0xc0420401d0

 

2.5 type定义类型

在别的程序中都会设有部分变量有着同样的内部结构,可是却代表完全两样的概念。 贰个类型注解语句创设了二个新的类型名称,和水保项目具备雷同的底层结构。

type 类型名字 底层类型

例如:

type Age int    //年龄

type Height int //身高

type Grade int  //分数

type绝不只是对应于C/C++中的typedef,它不是用于定义大器晚成多元的外号。更主要的是,它定义了风流倜傥密密层层互不相干的一举一动特征:通过那些互不相干的一坐一起特征,本质上相近的事物表现出差异事物的特点:整数还是平头,但年纪却不是惊人亦不是分数。大家能够分别为Age、Height、Grade定 义出下列分化的一颦一笑(表示为艺术只怕函数卡塔 尔(英语:State of Qatar):

type Age int    //年龄

type Height int //身高

type Grade int  //分数

 

func (a Age) IsOld() bool {

// 超过50岁算老年

return a > 50

}

func (h Height ) NeedTicket() bool {

// 高于120cm需要买票

return h > 120

}

func (g Grade) Pass() bool {

// 60分及格

return g >= 60

}

花色证明语句日常出以往包一流,由此倘若新创制的连串名字首字母大写,则在包外能够行使。对于每二个类型T,都有贰个对应的类型转变操作T(x),用于将x转换为T类型。

package main

 

import (

    "fmt"

)

 

type Integer int

 

func (a Integer) Less(b Integer) bool {

    return a < b

}

func main() {

    var a Integer = 1

    fmt.Println(a.Less(2))

    var b int

    //不能直接赋值,需要T(x)类型转换

    b = a

    b = int(a)

    fmt.Println(b)

}

 

2.6作用域

一个声称语句将次第中的实体和一个名字关闭,比方叁个函数或壹个变量。评释语句的功用域是指源代码中得以有效采用那么些名字的限量。

不用将功用域和生命周期同日而论。证明语句的效能域对应的是一个源代码的公文区域,它是二个编译时的质量。三个变量的生命周期是指程序运维时变量存在的可行时间段,在这里时间区域内,它能够被先后的其余一些援引,是三个周转时的概念。

语法块是由花括号所含有的大器晚成多级讲话。语法块内部宣称的名字是力不胜任被外表语法块访谈的。语句块决定了里面宣称的名字的作用域范围。有二个语法块为全方位源代码,称为全局语法块;然后是各样包的包语法块;每种for、if和switch语句的语法块;各类switch或select的道岔也是有单独的语法块;当然也可以有展现书写的语法块(花括号富含的说话)。

宣称语句对应的词法域决定了作用域范围的高低。对于内置的类型、函数和常量,举例int、len和true等都是大局效率域的;任何在函数外界注明的名字能够在包的别样源文件中访谈,是包级功效域。对于导入的包,则是对应源文件级的效能域。调节流标号,正是break、continue或goto语句后接着的这种标号,是函数级功能域。

当编译器境遇叁个名字引用时,假诺它是一个宣称,首先从最内层的功用域向全局功效域查找。假如搜索未果,则错误。即便名字在里面和外部分别注解过,则内部块的扬言首先被找到,它会隐瞒外界同名的评释。

2.7 数据输入输出

2.7.1 标准输出函数

Print( )函数接收私下认可格式将其参数格式化并写入标准输出。如若三个相邻的参数都不是字符串,会在它们的输出之间增加空格。再次来到写入的字节数和遭受的此外不当。函数原型如下:

func Print(a ...interface{}) (n int, err error)

 

Println( )与Print( )函数的功能基本后生可畏致,独一不一致的是在出口甘休后,自动扩充换行。函数原型如下:

func Println(a ...interface{}) (n int, err error)

 

Printf()函数依据format参数生成格式化的字符串并写入规范输出。重临写入的字节数和蒙受的别的不当。函数原型如下:

func Printf(format string, a ...interface{}) (n int, err error)

2.7.2 标准输入函数

Scan( )函数从行业内部输入扫描文本,将幸不辱命读取的空白分隔的值保存进成功传送给本函数的参数。换行视为空白。再次回到成功扫描的条文个数和际遇的别的错误。假使读取的家有家规比提供的参数少,会回来多少个错误报告原因。函数原型如下:

func Scan(a ...interface{}) (n int, err error)

Scanln相近Scan,但会在换行时停下扫描。最终四个条约后必需有换行或许达到截至地方。函数原型如下:

func Scanln(a ...interface{}) (n int, err error)

Scanf从专门的学问输入扫描文本,依照format 参数钦定的格式将不辱义务读取的空域分隔的值保存进成功传送给本函数的参数。再次回到成功扫描的条约个数和遇到的别的不当。函数原型如下:

 

func Scanf(format string, a ...interface{}) (n int, err error)

本文由澳门新萄京网址发布于澳门新萄京网址,转载请注明出处:常量和数据类型

关键词: