Go基础学习04-变量重声明;类型转换;类型断言;Unicode代码点;类型别名;潜在类型

news2024/11/17 21:52:13

目录

变量重声明

类型断言

类型转换

 类型转换注意事项

Unicode代码点

类型别名、潜在类型

  类型别名的意义


变量重声明

编写代码:

package main

import "fmt"

var container = []string{"Beijing", "Shanghai"}

func main() {
	fmt.Println(container)
	container = []string{"Hello", "Hi"}
	fmt.Printf("variable redeclare %s\n", container)
	container := map[int]string{1: "Beijing", 2: "Shanghai"}
	strings, ok := interface{}(container).([]string)
	if ok {
		fmt.Println("Container type is []string...")
		fmt.Println(strings)
	} else {
		fmt.Println("Container type is map...")
		fmt.Printf("strings is %v\n", strings)
	}
	fmt.Println(container)
}

        上述代码首先定义一个字符串数组,其名称为container,在main函数中,首先对container进行短变量重赋值,随后又对container使用短变量重新赋值,但这次赋值的对象类型不是[]string而是一个map类型,其key为int,value为string。此时产生的现象在Go中称为可重名变量的类型不同,原先类型为[]string,随后将其类型更改为map[int][string]。上述代码执行结果如下:

        在使用:=对变量进行重声明之后,如果前后对应的变量类型不一致,此时一般需要进行类型断言,来确定具体变量对应的类型如:是[]string还是map[int][string]以确定后面遍历操作。

        下面将补充一下类型转换以及类型断言相关知识: 

类型断言

        在本篇开篇提供的代码中:

         上述方框中的.([]string)就是类型断言:

        类型断言表达式的语法形式是x.(T)。其中的x代表要被判断类型的那个值。这个值当下的类型必须是接口类型的,不过具体是哪个接口类型其实是无所谓的。所以,当这里的container变量类型不是任何的接口类型时,我们就需要先把它转成某个接口类型的值(具体参考下面类型转换知识)。如果container是某个接口类型的,那么这个类型断言表达式就可以是container.([]string)。

        这里使用类型断言将接口类型转换为[]string,同时类型断言等式左边有两个变量,变量ok表示是否能将接口类型变量断言为字符串数组,如果可以断言,则ok值为true同时转换后的字符串数组结果存储到strings变量中;如果不能将接口类型的变量转换为字符串数组,此时ok的值为false,并且strings值为[](nil)参考上面代码运行结果。

类型转换

        类型转换的语法形式是T(x)。
        其中的x可以是一个变量,也可以是一个代表值的字面量(比如1.23和struct{}),还可以是一个表达式。如果是表达式,那么该表达式的结果只能是一个值,而不能是多个值。在这个上下文中,x可以被叫做源值,它的类型就是源类型,而那个T代表的类型就是目标类型。

        如果从源类型到目标类型的转换是不合法的,那么就会引发一个编译错误。

strings, ok := interface{}(container).([]string)

        上面代码中的interface{}(containter)就是类型转换,当container不是一个接口类型时,通过类型转换将其转换为接口类型。在Go语言中,interface{}代表空接口,任何类型都是它的实现类型。任何类型的值都可以很方便地被转换成空接口的值。

        关于上面interface{}中的{}的解释参考下面图片: 

 类型转换注意事项

对于类型转换而言常见的需要遵循的转换规则如下:

  1. 对于整数类型值、整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内
    就是合法的。
    1. uint8(255)可以把无类型的常量255转换为uint8类型的值,是因为255在 [0,255] 的范围内。但需要特别注意的是,源整数类型的可表示范围较大,而目标类型的可表示范围较小的情况,比如把值的类型从int16转换为int8,此时会涉及到类型值的截断(大范围变为小范围可能涉及到值的缩小)。
  2. 虽然直接把一个整数值转换为一个string类型的值是可行的,但值得关注的是,被转换
    的整数值应该可以代表一个有效的 Unicode 代码点,否则转换的结果将会是"�"(仅由高亮的问号组成的字符串值)。具体关于Unicode代码点的解释可以参考下面阐述。
  3. string类型与各种切片类型之间的互转需要遵守类型编码规则,如UTF-8编码或者其他形式。

         代码展示:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	// 类型转换范围限定演练
	srcNum := int16(-255)
	dstNum := int8(srcNum)
	fmt.Printf("srcNum:%d, dstNum:%d\n", srcNum, dstNum)
	/**
	Go语言中负数以补码的形式存在,补码:源码求反+1
	-255 :1111111100000001
	从16位转为8位,需要高位截断变为00000001,由于最高位是0所以表示正数,所以是1
	*/

	/**
	Go中有效的Unicode代码点是什么???
	在将一个整数值转换为字符串时,这个整数应该是一个有效的 Unicode 代码点的值。Unicode 是一个字符编码标准,它为世界上大多数的文字系统提供了一个唯一的码位。每个 Unicode 代码点都对应一个字符。
	在计算机中,字符通常以字节的形式存储,而每个字节可以表示 0 到 255 之间的整数值。当一个整数超出了这个范围,或者它不是一个有效的 Unicode 代码点时,尝试将它转换为字符串可能会导致无法正确显示该字符,从而出现替代字符,通常是 ""(一个黑色菱形,中间有一个问号)。
	例如,在 UTF-8 编码中,一个字符可能由一到四个字节表示。如果一个整数对应于一个超出常用 Unicode 字符范围的值(比如大于 0x10FFFF),或者它是一个用于表示字符属性的码点(比如一些控制字符),那么它可能无法被正确地转换为一个可打印的字符。
	在 Go 语言中,如果你使用 string() 函数将一个整数值转换为字符串,并且该值超出了有效的 Unicode 代码点范围,你可能会得到一个替代字符。为了避免这个问题,你应该确保转换的整数值在有效的 Unicode 范围内(通常是 0 到 0x10FFFF)。
	*/
	fmt.Println(string(65))
	fmt.Println(string(37))
	fmt.Println(string(-1))

	/**
	正确的将整数转为字符串应该使用Go中提供的转换工具
	如:strconv.Itoa()\strconv.FormatInt()
	*/

	num := -1
	fmt.Println(strconv.Itoa(num))
	fmt.Println(strconv.FormatInt(int64(num), 10))
}

        结果展示:

Unicode代码点

        在将一个整数值转换为字符串时,这个整数应该是一个有效的 Unicode 代码点的值。Unicode 是一个字符编码标准,它为世界上大多数的文字系统提供了一个唯一的码位。每个 Unicode 代码点都对应一个字符。 在计算机中,字符通常以字节的形式存储,而每个字节可以表示 0 到 255 之间的整数值。当一个整数超出了这个范围,或者它不是一个有效的 Unicode 代码点时,尝试将它转换为字符串可能会导致无法正确显示该字符,从而出现替代字符,通常是 ""(一个黑色菱形,中间有一个问号)。 例如,在 UTF-8 编码中,一个字符可能由一到四个字节表示。如果一个整数对应于一个超出常用 Unicode 字符范围的值(比如大于 0x10FFFF),或者它是一个用于表示字符属性的码点(比如一些控制字符),那么它可能无法被正确地转换为一个可打印的字符。 在 Go 语言中,如果你使用 string() 函数将一个整数值转换为字符串,并且该值超出了有效的 Unicode 代码点范围,你可能会得到一个替代字符。为了避免这个问题,你应该确保转换的整数值在有效的 Unicode 范围内(通常是 0 到 0x10FFFF)。

        Unicode代码点可以借助ASCII码表理解,如A对应的整数类型值为65,这一部分可以借助上面代码理解。

类型别名、潜在类型

        在Go语言中,可以使用关键字type声明自定义的各种类型,这些类型必须在Go语言基本类型和高级范畴之内。下面介绍类型别名以及潜在类型。

type Mystring = string

       这条声明语句表示,MyString是string类型的别名类型。顾名思义,别名类型与其源类型的
区别恐怕只是在名称上,它们是完全相同的。

        源类型与别名类型是一对概念,是两个对立的称呼。别名类型主要是为了代码重构而存在的。在Go语言中已经存在的有别名类型如:byte是unit8的类型别名,rune是int32的类型别名。

type Mystring string

        上述Mystring和string是两个不同的类型,Mstring是一个新的类型,不同于其他任何类型。

        这种方式也可以被叫做对类型的再定义。我们刚刚把string类型再定义成了另外一个类型Mystring。对于这里的类型再定义来说,string可以被称为Mystring的潜在类型。潜在类型的含义:
        某个类型在本质上是哪个类型或者是哪个类型的集合。潜在类型相同的不同类型的值之间是可以进行类型转换的。        

        因此,Mystring类型的值与string类型的值可以使用类型转换表达式进行互转。但对于集合类的类型[]Mystring与[]string来说这样做却是不合法的,因为[]Mystring与[]string的潜在类型不同,分别是Mystring和string。另外,即使两个类型的潜在类型相同,它们的值之间也不能进行判等或比较,它们的变量之间也不能赋值。

        代码演示:

 

package main

import (
	"fmt"
)

// 潜在类型
type MyString string

// 类型别名
type MyString2 = string

func main() {
	var name MyString
	name = "zhang san"
	var copyName string
	/**
	潜在类型相同的不同类型的值之间是可以进行类型转换的。
	即使两个类型的潜在类型相同,但这两个类型对应的变量之间也不能进行判等或者比较,也不能进行赋值,只能进行类型转换
	copyName = name 不允许的操作
	*/
	copyName = string(name)
	fmt.Println(name)
	fmt.Println(copyName)
	fmt.Println("=========================")
	var name2 MyString2
	name2 = "lisi"
	var copyName2 string
	copyName2 = name2
	fmt.Println(name2)
	fmt.Println(copyName2)
}

  类型别名的意义

        对于大型的代码库来说,能够重构其整体结构是非常重要的,包括修改某些 API 所属的包。大型重构应该支持一个过渡期:从旧位置和新位置获得的 API 都应该是可用的,而且可以混合使
用这些 API 的引用。Go 已经为常量、函数或变量的重构提供了可行的机制,但是并不支持类
型。类型别名提供了一种机制,它可以使得 oldpkg.OldType 和 newpkg.NewType 是相同的,并且引用旧名称的代码与引用新名称的代码可以互相操作。

        考虑将一个类型从一个包移动到另一个包中的情况,比如从 oldpkg.OldType 到newpkg.NewType。可以在包 oldpkg 中指定一个新类型的别名 type OldType = newpkg.NewType,这样以前的代码都无需修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt开发技巧(八)自带对话框的美化,内置快捷代码段,巧用匿名槽函数,另类动态换肤,资源动态加载

继续讲一些Qt开发中的技巧操作: 1.自带对话框的美化 Qt中有一些自带的对话框,比如文件选择对话框,颜色选择对话框等等,这些对话框看着跟系统的对话框没太大差别,实际这是Qt有意为之,为的是跟系统保持一致。…

欺诈文本分类检测(十七):支持分类原因训练

1. 引言 前文数据校正与增强进行了数据增强,本文将使用增强后的数据对模型进行进一步训练,以便得到能同时预测出分类标签、欺诈者、分类原因多个信息的模型。 为此,我们需要对整个训练过程进行调整,包括: 交叉训练逻…

苹果端侧AI布局深度分析

苹果 - 国际巨头的端侧 AI布局 深度分析 1.1.1 苹果AI:模型侧:MM1 3月,苹果发布多模态大模型MM1,拥有高达300亿参数。MM1融合密集模型与MoE变体,涵盖300亿、70亿、30亿参数版。MM1预训练指标领先,在多个多…

ubuntu 安装k8s

#关闭 Swap 内存,配置完成建议重启一下 nano /etc/fstab #注释下面相似的一行 #/swapfile none swap sw 0 0 #重启 reboot#部属k8s apt update && apt install -y apt-transport-https 下载 gpg 密钥 curl https://mi…

基于SpringBoot+Vue的高校实习管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…

一次眼睛受损然后恢复的过程

由于多年没有社交比较宅,多年长期盯着电脑和手机,没有保护好眼睛 之前早上醒来有一段时间我眼睛老是分泌各种乱起八遭的东西,导致我眼睛看不清, 2023年3月有天的早上,我又不小心眼睛揉出血了,出门上班路上的时候才知道有这个问题,第二天早上就挂了去了眼科,医生给我开了如下的药…

单细胞转录组|scATAC-seq 数据整合

引言 本文在此展示了如何将多个源自人类外周血单核细胞的单细胞染色质数据集进行整合。其中一个数据集是通过10x Genomics的多组学技术获得的,它涵盖了每个细胞的DNA可及性和基因表达数据。另一个数据集则是通过10x Genomics的单细胞ATAC测序(scATAC-seq)技术得到的…

Mybatis-Plus自动填充时间的配置类

引言:在现代软件开发中,数据库操作是不可或缺的一部分。为了确保数据的准确性和完整性,我们常常需要在数据库记录中添加时间戳,例如创建时间和更新时间。MyBatis-Plus作为一个流行的持久层框架,提供了灵活的机制来实现…

官方权威解读|CNAS-CL01计量溯源性部分解读,供CNAS软件测试实验室参考

CNAS-CL01《检测和校准实验室能力认可准则》是软件测试实验室申请CNAS资质,建设符合CNAS要求的实验室质量管理体系时必须要参考的一部强制性准则。CNAS-CL01一共分为五大核心部分:通用要求、结构要求、资源要求、过程要求和管理体系要求。前面的文章中我…

【零散技术】微信支付保姆教程(一)

序言:时间是我们最宝贵的财富,珍惜手上的每个时分 微信支付十余年,早已成为国内必不可少的支付工具。但是开发对接中 繁杂的各类参数与文档,以及各种证书的申请,着实也成了不少开发者的噩梦,那么今天我们来看看,如何申…

3-3 AUTOSAR RTE 对SR Port的作用

返回总目录->返回总目录<- 一、前言 RTE作为SWC和BSW之间的通信机构,支持Sender-Receiver方式实现ECU内及ECU间的通信。 对于Sender-Receiver Port支持三种模式: 显式访问:若运行实体采用显示模式的S/R通信方式,数据读写是即时的;隐式访问:当多个运行实体需要读取…

小阿轩yx-案例:代码管理系统简介与部署

小阿轩yx-案例&#xff1a;代码管理系统简介与部署 前言 开发一个项目时&#xff0c;如果只有几十行代码或几百行代码时维护还算简单&#xff0c;但是代码数量达到一定程度或两三个人共同开发一个项目时&#xff0c;就很容易会出现代码混乱、冲突、排错难等问题。代码编写完成…

vue3中< keep-alive >页面实现缓存及遇到的问题

vue3中< keep-alive >页面实现缓存及遇到的问题 实现原理&#xff1a;keep-alive 是 Vue 的内置组件&#xff0c;当它包裹动态组件时&#xff0c;会缓存不活动的组件实例&#xff0c;而不是销毁它们。实现不同路由是否缓存只需要设置对应路由参数keepAlive为true&#xf…

Excel里的 $ 是什么意思,绝对引用用法详解来了

大家好&#xff0c;这里是效率办公指南&#xff01; &#x1f511; 在Excel中&#xff0c;$符号是一个功能强大的工具&#xff0c;它用于实现单元格引用的绝对引用和混合引用。了解它的用法对于编写公式和处理数据至关重要。今天&#xff0c;我们将详细介绍$符号的用法和一些实…

【C++】设计用户级缓冲区

目录 缓冲区功能分析 缓冲区空间分配策略分析 数据设计和函数介绍 完整代码 接口介绍 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 缓冲区功能分析 1.可以向缓冲区写入数据 2.可用从缓冲区读取数据 3.可用窥探数据——把数据拷贝给上层&#xff0c;但缓冲区数据不减少 …

巧用枚举消除条件判断

shigen坚持更新文章的博客写手&#xff0c;记录成长&#xff0c;分享认知&#xff0c;留住感动。个人IP&#xff1a;shigen 在上一篇的文章结合HashMap与Java 8的Function和Optional消除ifelse判断中有讲到如何结合HashMap与Java 8的Function和Optional消除ifelse判断&#xff…

校园二手交易平台的小程序+ssm(lw+演示+源码+运行)

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

Transformer: Attention is all you need

Transformer于2017年提出&#xff0c;最开始应用于NLP领域&#xff0c;随着Transformer的快速发展&#xff0c;在视觉领域中也越来越多的论文或应用用到了Transformer&#xff0c;这里记录一下自己学习的一些知识点。 PDF&#xff1a; 《Attention Is All You Need》 Code: att…

【HTML5】html5开篇基础(3)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

带您了解《人工智能机器视觉应用工程师》

人工智能机器视觉应用是指利用人工智能技术和机器视觉技术相结合&#xff0c;使机器能够像人类一样通过视觉感知和理解环境&#xff0c;从而实现各种应用。随着人工智能技术的不断发展&#xff0c;机器视觉应用在各个领域得到了广泛应用。 在工业制造领域&#xff0c;人工智能机…