08-常量

一 数据类型转换

1.1 显式转换

Go在不同类型的变量之间赋值时需要显式转换。也就是说Golang中数据类型不能自动转换。

1.2 数值类型转换

var i int32 = 100
var n1 float64 = float64(i)
fmt.Printf("n1=%v", n1) //输出100

注意:在转换中,比如将int64转成​int8【-128---127】​,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样。 因此在转换时,需要考虑范围。

1.3 基本数据类型与字符串转换

基本数据类型转字符串:fmt.Sprintf();该函数会返回转换后的字符串

var b bool = true
var str string

str = fmt.Sprintf("%t", b)
fmt.Printf(str) //true

字符串转基本数据类型:使用包strconv

var str string = "true"
var b bool
b, _ = strconv.ParseBool(str)
fmt.Printf("%v", b)

注意:在将​​String​​​类型转成基本数据类型时,要确保​​String​​​类型能够转成有效的数据,比如可以把"123",转成一个整数,但不能转换"hello",如果这样做,Golang 直接将其转成​​0​​​,其它类型也是一样的道理,如:​​float => 0 bool => false​​。

二 类型别名

2.1 类型别名的使用

Go在1.9版本加入了类型别名。主要用于代码升级、迁移中类型的兼容问题(C/C++中使用宏来解决重构升级带来的问题)。

Go1.9之前的版本内部定义了新的类型byte和rune,用于指代​​uint8​​​和​​int32​​:

type byte uint8
type rune int32

Go1.9之后​​uint8​​​和​​int32​​使用了类型别名:

type byte = uint8        // 使用 = 号定义后,都会按照等号右边的类型打印、计算
type rune = int32

类型定义是定义了一个全新的类型的类型。类型别名只是某个类型的小名,并非创造了新的类型:

type MyInt int                          // 类型定义
type AliasInt = int // 类型别名,支持使用括号,同时起多个别名

var a1 MyInt
fmt.Printf("a1 type: %T\n", a1) //main.MyInt

var a2 AliasInt
fmt.Printf("a2 type: %T\n", a2) //int

2.2 不同包下的类型定义

如下示例,在项目根目录新建文件夹​​mypack​​​,在该目录建立​​person.go​​文件:

package mypack

import "fmt"

type Person struct {

}

func (p *Person)Run() {
fmt.Println("run...")
}

在main.go中,如下使用:

package main

import (
"TestGo/mypack" // // TestGo 是 go.mod文件中定义的项目名:module TestGo
"fmt"
)

type Student mypack.Person

func (s *Student) Study() {
fmt.Println("study...")
}

func main() {

s := &Student{}
s.Study()

}

2.3 不同包下的类型别名

2.2 中的案例如果将类型定义改为类型别名:

type Student = mypack.Person                // 这时Student的方法就会报错:无法为 Person 添加新的方法

使用方式:必须直接在person文件中直接使用类型别名

package mypack

import "fmt"

type Person struct {

}

func (p *Person)Run() {
fmt.Println("run...")
}


type Student = Person

func (p *Student) Study() {
fmt.Println("study...")
}

main中调用别名方法:

package mypack

import "fmt"

type Person struct {

}

func (p *Person)Run() {
fmt.Println("run...")
}


type Student = Person

func (p *Student) Study() {
fmt.Println("study...")
}

三 Go的类型系统补充

3.1 命名类型和未命名类型

  • 命名类型:Named Type。类型通过标识符、自定义类型表示
  • 未命名类型:Unamed Type。也称为类型字面量(Type Literal),由预声明类型、关键字、操作符等组合而成,如array、slice、channel、pointer、function、未使用type定义的struct、未使用type定义的interface。

示例:

// 命名类型,其类型是 Person
type Person struct {
name string
}
// 未命名类型,其类型是 struct { name string }
p := struct {
name string
}

3.2 底层类型

所有类型都有一个底层类型 underlying type,其规则如下:

  • 预声明类型(Pre-declared types)和类型字面量(type literals)的底层类型是他们自身
  • 自定义类型​​type newtype oldtype​​中newtype的底层类型是逐层递归向下查找的,直到找到oldtype的预声明类型或字面量类型

3.3 Go中的类型相同

Go中类型相同的规范:

  • 命名类型的数据类型相同:声明语句必须完全相同
  • 未命名类型数据类型相同:类型声明字面量结构相同,且内部元素的类型相同
  • 命名类型与未命名类型永远不同
  • 通过类型别名语句声明的两个类型相同。类型别名语法:​​type T1 = T2​