32、Go 结构体 - type 类型别名和用户自定义类型

作者: 温新

分类: 【Go基础】

阅读: 520

时间: 2023-08-29 16:16:18

hi,我是温新

在 Go 语言中,自定义类型指的是使用 type 关键字定义的新类型,它可以是基本类型的别名,也可以是结构体、函数等组合而成的新类型。自定义类型可以帮助我们更好地抽象和封装数据,让代码更加易读、易懂、易维护。

当基本的数据类型(string、int、float、bool等)不够用时,用户可以使用 type 关键字进行自定义类型。type 只有两种使用方式,一种类型别名,另一种是自定义类型

本篇文章将学习这两种方式。

类型别名与类型定义

类型别名

语法如下:

type TypeAlias = Type
// type 类型别名 = 类型

类型别名规定:TypeAlias 只是 Type 的别名,本质上 TypeAliasType 是同一个类型。如同李四的别名是二狗子,不不管你叫二狗子还是李四,都是他。

类型定义

语法如下:

type newType = Type
// type 新类型 = 类型

案例:

package main

import "fmt"

// 类型定义
type newInt int

// 类型别名
type newString = string

func main() {
    // 将 newStr 类型声明为 newString
    var newStr newString = "王美丽"
    // 将 num 声明为 newInt 类型
    var num newInt = 19

    fmt.Printf("newStr 的数据类型 %T,内容是 %s\n", newStr, newStr)
    fmt.Printf("num 的数据类型 %T,内容是 %d\n", num, num)
}

输出结果

newStr 的数据类型 string,内容是 王美丽
num 的数据类型 main.newInt,内容是 19

类型声明与类型定义有什么区别?

两者之间的区别在于,类型别名只是给现有类型取了一个别名;而类型定义则是完全定义了一种新的类型。

非本地类型不能定义方法

package main

import "time"

// 定义一个方法别名
type myTime = time.Time

func main() {

}

// 为 myTime 添加一个函数
func (m myTime) getMyTime() {
}

(m myTime) 这里会报错:Cannot define new methods on the non-local type 'time.Time'。不能在一个非本地的类型 time.Duration 上定义新的方法。非本地类型指的就是 time.Duration 不是在 main 包中定义的,而是在 time 包中定义的,与 main 包不在同一个包中,因此不能为不在一个包中的类型定义方法。

解决这个问题有两种方法,如下:

1、type myTime =time.Time 修改为type myTime time.Duration,也就是把 myTime从别名改为类型;

2、把 myTime 的别名定义放在 time 包中。

用户自定义类型

在 Go 语言中,type 是一个非常重要的关键字,它的常用用法有这几种:类型别名、类型定义、定义结构体、定义接口、类型查询、定义函数。

定义结构体

在之前的文章已经学习过结构体,这里作一个简单的回顾吧。

package main

import "fmt"

func main() {
    p1 := MyPerson{
        name:   "王美丽",
        gender: "女",
    }

    fmt.Println(p1)
}

// 定义结构体
type MyPerson struct {
    name, gender string
}

定义接口

关于接口,这里只作一个简单的案例进行演示。关于接口的知识将在后续文章中学习。

package main

import "fmt"

func main() {
    xiaomi := new(Xiaomi)
    xiaomi.name = "小米13"
    xiaomi.Call() // 小米13:可以打电话
}

// 定义一个电话接口
type Phone interface {
    Call()
}

// 定义结构体
type Xiaomi struct {
    name string
}

// 定义一个方法
func (xiaomi *Xiaomi) Call() {
    fmt.Printf("%s:可以打电话", xiaomi.name)
}

定义函数

package main

import (
    "fmt"
    "strconv"
)

func main() {
    result := getMyFun()
    fmt.Println(result(10, 10))
}

// 定义一个函数
type MyFun func(int, int) string

// 该函数返回值是 MyFun 类型
func getMyFun() MyFun {
    fun := func(m, n int) string {
        str := strconv.Itoa(m) + strconv.Itoa(n)

        return str
    }

    return fun
}

类型查询

类型查询,就是根据变量来查询它的类型。Golang 中有一个特殊的类型interface{},这个类型可以被赋予任何类型的变量的值,如果想要知道哪个类型的赋值给了interface{}类型变量,就需要使用类型查询,案例如下:

package main

import "fmt"

func main() {
    var variableName interface{} = "abc"

    switch v := variableName.(type) {
    case string:
        fmt.Println("字符串")
    case int:
        fmt.Println("整型")
    default:
        fmt.Println("其他类型", v)
    }
}

如果使用.(type)查询类型的变量不是 interface{} 类型,则在编译时报错:cannot type switch on non-interface value a (type string)

若在 switch 以外的地方使用.(type),则在编译时报错:use of .(type) outside type switch

由此可知,使用type进行类型查询时,只能在switch中使用,且使用类型查询必须是interface{}

后面要停更 2 个星期了,今天把库存都发了出来。我们 9 月中旬再见。

请登录后再评论