大家好,我又来了,接着上一期我们搭建了golang的环境变量后,我们接着看一下编程的基础常识。
众所周知在编程中,我们涉及到一下常用的东西:
- 数据类型
- 变量和常量
- 运算符
- 语句
- 数组、集合
- 方法
- 资源引入
- 包
1、数据类型
在go语言中,我们常见的数据类型有很多,但是值得注意的是,他们都是小写!都是小写!都是小写!
package builtin
// bool is the set of boolean values, true and false.
type bool bool
// true and false are the two untyped boolean values.
const (
true = 0 == 0 // Untyped bool.
false = 0 != 0 // Untyped bool.
)
// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8
// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16
// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32
// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64
// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8
// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16
// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32
// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64
// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32
// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64
// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64
// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128
// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string
// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int
// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint
// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int
// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int
// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int
// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32
// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64
复制代码
在上面的源码摘录中,我们可以看到go语言完整的数据类型。但是,我们总结下常用的如下:
- int、uint 整形、无符号整形
- int8、int16(2字节,-32768~32767)、int32(rune)、int64
- uint8、uint16(2字节,0~65535)、uint32、uint64
- string 字符串(原生utf-8编码支持)
- bool 布尔型
- float 浮点型
- float32、float64 (4/8字节,精确到小数后7/15位)
- byte 1字节 uint8的别名
- nil 空类型
- complex64、complex128 复数类型(实数、虚数),8字节、16字节
- uintptr 足够大的位模式保存指针的整数类型(uintptr is an integer type that is large enough to hold the bit pattern of any pointer.)
同样的,还有一些派生数据类型(我个人喜欢称之为扩展数据类型或者是包装数据类型),基本如下:
- 指针类型(Pointer)
- 数组类型
- 结构化类型(struct)
- Channel 类型
- 函数类型
- 切片类型
- 接口类型(interface)
- map类型
当然这些扩展数据类型我们将在以后一一阐述。
go 1.9版本对于数字类型,无需定义int及float,系统会自动识别。
附赠demo小案例(完成变量的申明和使用,以及注意事项)
package main
//导包
import "fmt"
//分组申明变量
var (
personA = "小王"
personC = "小张"
ageA = 18
)
func main() {
//快捷申明变量 省却var标识符
mName := "程先生"
//var 标明数据是变量
var mSex = "汉子"
fmt.Println(mName + ",哎哟我去,你是" + mSex)
var a = 1.5
var b = 2
fmt.Println(a, " ====我是分隔符==== ", b)
fmt.Println(personA, " ====我是分隔符==== ", personC, " ====我是分隔符==== ", ageA)
}
复制代码
当然,运行结果如下:
程先生,哎哟我去,你是汉子
1.5 ====我是分隔符==== 2
小王 ====我是分隔符==== 小张 ====我是分隔符==== 18
复制代码
在上面的代码中,有下面一些操作
- 必须申明包,且主程序包为:main
- 入口函数为:main,且没有任何参数
- var为变量申明标识符
- 变量可以分组申明(导包可以分组吗?)
- 可以采用快捷申明变量 := ,注意:仅仅能在函数中使用
- 变量的基本数据类型无需申明,系统会自动推导
- 当然手动申明变量类型如: var aa string = "糍粑"
- 所有的变量都是使用过的(未使用的变量会产生编译异常)
- java中输出语句基本数据类型和string可以通过“+”连接,但是go中不允许这种骚操作
- 变量可以即时申请
- 无需“;”结尾,换行既是语句的结束
- 虽然允许多变量一行赋值,但是不推荐如此做,所以也未举例
常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量定义格式: const identifier [type] = value
如下:
- 显式类型定义: const b string = "abc"
- 隐式类型定义: const b = "abc"
- 多个相同类型的声明可以简写为: const c_name1, c_name2 = value1, value2 (当然,我一样不推荐这样定义,降低了可读性)
那么我们试一试小demo
//在main方法中执行下面代码段
const PI = 3.14
r := 4
fmt.Println("圆的面积为:", PI*r*r)
复制代码
在我们运行后代码报错如下:
# command-line-arguments
./demo001.go:26:38: constant 3.14 truncated to integer
复制代码
上面代码提示PI被截断为整数,但是程序却没能成功运行,是不是go不支持数据类型自动转换呢?
我们这时候考虑一下把常量显示申明为float32试一试:
const PI float32 = 3.14
r := 4
fmt.Println("圆的面积为:", PI*r*r)
复制代码
这次更加凄惨,代码甚至不能通过编译,在“PI *r *r”这里提示类型匹配错误!emmmm····
我们只能选择把r申明为float试试,如下:
const PI = 3.14
r := 4.0
fmt.Println("圆的面积为:", PI*r*r)
复制代码
恭喜,本次编译通过,且有输出内容,如下:
圆的面积为: 50.24
复制代码
当然如下代码也能成功运行:
const PI float32 = 3.14
var r float32 = 4.0
fmt.Println("圆的面积为:", PI*r*r)
复制代码
这说明,go是一个严格强调数据类型匹配的语言。
当然,前面我们看到变量分组申明,那么这里我们常量一样可以分组申明:
const (
OK = 0
ERROR = 1
EMPUTY = -1
)
复制代码
常量申明中的 iota
ota,特殊常量,可以认为是一个可以被编译器修改的常量。 在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。
我们来枚举一些常量:
const (
a = iota
b = iota
c = iota
)
//第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:
const (
a = iota
b
c
)
复制代码
当然我们也可以看看别人教程(菜鸟教程-> Go语言常量)所书写的例子:
package main
import "fmt"
func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
}
复制代码
运行结果如下:
0 1 2 ha ha 100 100 7 8
复制代码
上面的例子,说实话,有一点绕,同时我也不建议在实际开发中写出这种骚操作,毕竟这样写可能会被队友打死。
当然iota也可以加入到移位运算中:
package main
import "fmt"
const (
//第一个iota默认值是0,左移位1,则不变
i=1<<iota
//左移位 0+1,3的二进制是0011,左移位一次就是0110,十进制结果为6
j=3<<iota
//这里实际代码是: k = 3 << iota ,按照上面的推算则是左移位1+1,下面的l同理
k
l
)
func main() {
fmt.Println("i=",i)
fmt.Println("j=",j)
fmt.Println("k=",k)
fmt.Println("l=",l)
}
复制代码
输出结果:
i= 1
j= 6
k= 12
l= 24
复制代码
总结
变量的申明:
- var name [type] = value
- 方法内 name := value
- 变量组申明 var (name = value)
常量的申明:
- const name [type] = value
- 常量组申明:const (name = value)
其他:
- 内置函数
- 变量常量数据类型自推导
- 严格的数据类型限制