首页 > 其他分享 >go语言基础-基本类型和布尔

go语言基础-基本类型和布尔

时间:2023-08-04 13:45:12浏览次数:35  
标签:语言 int 运算符 类型 使用 go Go true 布尔

这部分讲解有关布尔型、数字型和字符型的相关知识。

表达式是一种特定类型的值,它可以由其他的值以及运算符组合而成。每个类型都定义了可以和自己结合的运算符集合,如果你使用了不在这个集合中的运算符,在编译时获得编译错误。

一元运算符只可以用于一个值的操作(作为后缀),而二元运算符则可以和两个值或者操作数结合(作为中缀)。

只有两个类型相同的值才可以和二元运算结合,另外要注意的是,Go 是强类型语言,因此不会进行隐式转换,任何不同类型之间的都必须显式转换。Go不存在像C那样的运算符重载,表达式的解析顺序是从左至右。

你可以在前面的文章基本结构种找到有关算符优先级的相关信息,优先级算符的算符在相同条件的情况下将被优先执行。但是你可以通过使用逗号将其中的表达式括起来,以人为地提出某个表达的攻击优先级。

布尔值

一个简单的例子:var b bool = true

布尔型的值只能是常量 true 或 false。

类型相同的值可以使用两个==或者不等!=运算符来进行比较并获得一个布尔型的值。

当携带的值是两个的值的时候会返回true,否则返回false,并且只有在两个的值的类型相同的情况下才可以使用。

var aVar = 10
aVar == 5 -> false
aVar == 10 -> true

当不等携带的值是不同的时候会返回true,否则返回false

var aVar = 10
aVar != 5 -> true
aVar != 10 -> false

对于值之间的比较有非常严格的限制,只有两个类型相同的值才可以进行比较,如果值的类型是接口,它们也必须都实现了相同的接口,如果其中一个值是常量,那么另外一个值的类型必须和该常量类型相兼容的。以上如果条件不满足,则其中一个值的类型必须在被转换为和另外一个值的类型相同之后才可以进行比较。

布尔型的常量和变量也可以通过和逻辑运算(非!、与&&、或||)结合来产生另外一个布尔值,这样的逻辑语句就其本身而言,并不是一个完整的Go语句。

逻辑值可以被用于条件结构中的条件语句,以便测试某个条件是否满足。另外,与&&、或||==或者不等!=属于二元运算符,而不!属于一元运算符。在接下来的内容中,我们会用 T 来代表条件符合的语句,用 F 来代表条件不符合的语句。

Go语言中包含以下逻辑时序:

非运算符:!

!T -> false
!F -> true

非运算符用于取得和布尔值相反的结果。

与运算符:&&

T && T -> true
T && F -> false
F && T -> false
F && F -> false

只有当两边的值都为 true 的时候,和运算符的结果才是 true

或运算符:||

T || T -> true
T || F -> true
F || T -> true
F || F -> false

只有当两边的值都为 false 的时候,或运算符的结果才是 false,其中任意一边的值为 true 就能够使得该表达式的结果为 true

在 Go 语言中,&& 和 || 是具有快捷性质的运算符,当运算符左边表达式的值已经能够决定整个表达式的值的时候(&& 左边的值为 false|| 左边的值为 true),运算符右边的表达式将不会被执行。利用这个性质,如果你有多个条件判断,应当将计算过程较为复杂的表达式放在运算符的右侧以减少不必要的运算。

利用括号同样可以升级某个表达式的运算优先级。

在格式化输出时,你可以使用 %t 来表示你要输出的值为布尔型。

布尔值(以及任何结果为布尔值的表达式)最常用在条件结构的条件语句中,例如:if、for 和 switch 结构。

对于布尔值的好的命名能够很好地提升代码的可读性,例如以 is 或者 Is 开头的 isSortedisFinishedisVisible,使用这样的命名能够在阅读代码的获得阅读正常语句一样的良好体验,例如标准库中的 unicode.IsDigit(ch)

数字类型

整型和浮点型

Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。

Go 也有基于架构的类型,例如:intuint 和 uintptr

这些类型的长度都是根据运行程序所在的操作系统类型所决定的:

  • int 和 uint 在 32 位操作系统上,它们均使用 32 位(4 个字节),在 64 位操作系统上,它们均使用 64 位(8 个字节)。
  • uintptr 的长度被设定为足够存放一个指针即可。

Go 语言中没有 float 类型。(Go语言中只有 float32 和 float64)没有 double 类型。

与操作系统架构无关的类型都有固定的大小,并在类型的名称中就可以看出来:

整数:

  • int8(-128 -> 127)
  • int16(-32768 -> 32767)
  • int32(-2,147,483,648 -> 2,147,483,647)
  • int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)

无符号整数:

  • uint8(0 -> 255)
  • uint16(0 -> 65,535)
  • uint32(0 -> 4,294,967,295)
  • uint64(0 -> 18,446,744,073,709,551,615)

浮点型(IEEE-754 标准):

  • float32(+- 1e-45 -> +- 3.4 * 1e38)
  • float64(+- 5 * 1e-324 -> 107 * 1e308)

int 型是计算最快的一种类型。

整型的零值为 0,浮点型的零值为 0.0

float32 精确到小数点后 7 位,float64 精确到小数点后 15 位。由于精确度的缘故,你在使用 == 或者 != 来比较浮点数时应当非常小心。你最好在正式使用前测试对于精确度要求较高的运算。

你应该尽可能地使用 float64,因为 math 包中所有有关数学运算的函数都会要求接收这个类型。

你可以通过增加前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示 16 进制数(如:0xFF),以及使用 e 来表示 10 的连乘(如: 1e3 = 1000,或者 6.022e23 = 6.022 x 1e23)。

你可以使用 a := uint64(0) 来同时完成类型转换和赋值操作,这样 a 的类型就是 uint64

Go 中不允许不同类型之间的混合使用,但是对于常量的类型限制非常少,因此允许常量之间的混合使用,下面这个程序很好地解释了这个现象(该程序无法通过编译):

package main

func main() {
    var a int
    var b int32
    a = 15
    b = a + a     // 编译错误
    b = b + 5    // 因为 5 是常量,所以可以通过编译
}

如果你尝试编译该程序,则将得到编译错误cannot use a + a (value of type int) as int32 value in assignment。

同样地,int16 也不能够被隐式转换为 int32

下面这个程序展示了通过显式转换来避免这个问题。

package main

import "fmt"

func main() {
    var n int16 = 34
    var m int32
    // compiler error: cannot use n (type int16) as type int32 in assignment
    //m = n
    m = int32(n)

    fmt.Printf("32 bit int is: %d\n", m)
    fmt.Printf("16 bit int is: %d\n", n)
}

输出

32 bit int is: 34
16 bit int is: 34

格式化说明符

在格式化字符串里,%d 用于格式化整数(%x 和 %X 用于格式化 16 进制表示的数字),%g 用于格式化浮点型(%f 输出浮点数,%e 输出科学计数表示法),%0nd 用于规定输出长度为 n 的整数,其中开头的数字 0 是必须的。

%n.mg 用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串 %5.2e 来输出 3.4 的结果为 3.40e+00

数字值转换

当进行类似 a32bitInt = int32(a32Float) 的转换时,小数点后的数字将被丢弃。这种情况一般发生当从取值范围较大的类型转换为取值范围较小的类型时,或者你可以写一个专门用于处理类型转换的函数来确保没有发生精度的丢失。下面这个例子展示如何安全地从 int 型转换为 int8

func Uint8FromInt(n int) (uint8, error) {
    if 0 <= n && n <= math.MaxUint8 { // conversion is safe
        return uint8(n), nil
    }
    return 0, fmt.Errorf("%d is out of the uint8 range", n)
}

或者安全地从 float64 转换为 int

func IntFromFloat64(x float64) int {
    if math.MinInt32 <= x && x <= math.MaxInt32 { // x lies in the integer range
        whole, fraction := math.Modf(x)
        if fraction >= 0.5 {
            whole++
        }
        return int(whole)
    }
    panic(fmt.Sprintf("%g is out of the int32 range", x))
}

不过如果你实际存的数字超出你要转换到的类型的取值范围的话,则会引发 panic。

复数

Go 拥有以下复数类型:

complex64 (32 位实数和虚数)
complex128 (64 位实数和虚数)

复数使用 re+imI 来表示,其中 re 代表实数部分,im 代表虚数部分,I 代表根号负 1。

实例:

var c1 complex64 = 5 + 10i
fmt.Printf("The value is: %v", c1)
// 输出: 5 + 10i

如果 re 和 im 的类型均为 float32,那么类型为 complex64 的复数 c 可以通过以下方式来获得:

c = complex(re, im)

函数 real(c) 和 imag(c) 可以分别获得相应的实数和虚数部分。

在使用格式化说明符时,可以使用 %v 来表示复数,但当你希望只表示其中的一个部分的时候需要使用 %f

复数支持和其它数字类型一样的运算。当你使用等号 == 或者不等号 != 对复数进行比较运算时,注意对精确度的把握。cmath 包中包含了一些操作复数的公共方法。如果你对内存的要求不是特别高,最好使用 complex128 作为计算类型,因为相关函数都使用这个类型的参数。

位运算

位运算只能用于整数类型的变量,且需当它们拥有等长位模式时。

%b 是用于表示位的格式化标识符。

二元运算符

按位与 &

对应位置上的值经过和运算结果,具体参见和运算符(第 4.5.1 节),并将 T (true) 替换为 1,将 F (false) 替换为 0

  1 & 1 -> 1
  1 & 0 -> 0
  0 & 1 -> 0
  0 & 0 -> 0

按位或 |

对应位置上的值经过或运算结果,具体参见或运算符(第 4.5.1 节),并将 T (true) 替换为 1,将 F (false) 替换为 0

  1 | 1 -> 1
  1 | 0 -> 1
  0 | 1 -> 1
  0 | 0 -> 0

按位异或 ^

对应位置上的值根据以下规则组合

  1 ^ 1 -> 0
  1 ^ 0 -> 1
  0 ^ 1 -> 1
  0 ^ 0 -> 0

位清除 &^:将指定位置上的值设置为 0

 package main
 import "fmt"
 func main() {
     var x uint8 = 15
     var y uint8 = 4
     fmt.Printf("%08b\n", x &^ y);  // 00001011
 }

一元运算符

按位补足 ^

该运算符与异或运算符一同使用,即 m^x,对于无符号 x 使用 “全部位设置为 1” 的规则,对于有符号 x 时使用 m=-1。例如:

  ^10 = -01 ^ 10 = -11

位左移 <<

  • 用法:bitP << n

  • bitP 的位向左移动 n 位,右侧空白部分使用 0 填充;如果 n 等于 2,则结果是 2 的相应倍数,即 2 的 n 次方。例如:

  • 1 << 10 // 等于 1 KB
      1 << 20 // 等于 1 MB
      1 << 30 // 等于 1 GB

    位右移 >>

    • 用法:bitP >> n
    • bitP 的位向右移动 n 位,左侧空白部分使用 0 填充;如果 n 等于 2,则结果是当前值除以 2 的 n 次方

当希望把结果赋值给第一个操作数时,可以简写为 a <<= 2 或者 b ^= a & 0xffffffff

位左移常见实现存储单位的用例

使用位左移与 iota 计数配合可优雅地实现存储单位的常量枚举:

type ByteSize float64
const (
    _ = iota // 通过赋值给空白标识符来忽略值
    KB ByteSize = 1<<(10*iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

在通讯中使用位左移表示标识的用例

type BitFlag int
const (
    Active BitFlag = 1 << iota // 1 << 0 == 1
    Send // 1 << 1 == 2
    Receive // 1 << 2 == 4
)

flag := Active | Send // == 3

逻辑运算符

Go 中拥有以下逻辑运算符:==!=<<=>>=

它们之所以被称为逻辑运算符是因为它们的运算结果总是为布尔值 bool。例如:

b3 := 10 > 5 // b3 is true

算术运算符

常见可用于整数和浮点数的二元运算符有 +-* 和 /

(相对于一般规则而言,Go 在进行字符串拼接时允许使用对运算符 + 的重载,但 Go 本身不允许开发者进行自定义的运算符重载)

/ 对于整数运算而言,结果依旧为整数,例如:9 / 4 -> 2

取余运算符只能作用于整数:9 % 4 -> 1

整数除以 0 可能导致程序崩溃,将会导致运行时的恐慌状态(如果除以 0 的行为在编译时就能被捕捉到,则会引发编译错误);后面 将会详细讲解如何正确地处理此类情况。

浮点数除以 0.0 会返回一个无穷尽的结果,使用 +Inf 表示。

尝试编译

你可以将语句 b = b + a 简写为 b += a,同样的写法也可用于 -=*=/=%=

对于整数和浮点数,你可以使用一元运算符 ++(递增)和 --(递减),但只能用于后缀:

i++ -> i += 1 -> i = i + 1
i-- -> i -= 1 -> i = i - 1

同时,带有 ++ 和 -- 的只能作为语句,而非表达式,因此 n = i++ 这种写法是无效的,其它像 f(i++) 或者 a[i]=b[i++] 这些可以用于 C、C++ 和 Java 中的写法在 Go 中也是不允许的。

在运算时 溢出 不会产生错误,Go 会简单地将超出位数抛弃。如果你需要范围无限大的整数或者有理数(意味着只被限制于计算机内存),你可以使用标准库中的 big 包,该包提供了类似 big.Int 和 big.Rat 这样的类型。

随机数

些像游戏或者统计学类的应用需要用到随机数。rand 包实现了伪随机数的生成。

示例 random.go 演示了如何生成 10 个非负随机数:

package main
import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    for i := 0; i < 10; i++ {
        a := rand.Int()
        fmt.Printf("%d / ", a)
    }
    for i := 0; i < 5; i++ {
        r := rand.Intn(8)
        fmt.Printf("%d / ", r)
    }
    fmt.Println()
    timens := int64(time.Now().Nanosecond())
    rand.Seed(timens)
    for i := 0; i < 10; i++ {
        fmt.Printf("%2.2f / ", 100*rand.Float32())
    }
}
可能的输出

816681689 / 1325201247 / 623951027 / 478285186 / 1654146165 /
1951252986 / 2029250107 / 762911244 / 1372544545 / 591415086 / / 3 / 0 / 6 / 4 / 2 /22.10
/ 65.77 / 65.89 / 16.85 / 75.56 / 46.90 / 55.24 / 55.95 / 25.58 / 70.61 /

函数 rand.Float32 和 rand.Float64 返回介于 [0.0,1.0) 之间的伪随机数,其中包括 0.0 但不包括 1.0。函数 rand.Intn 返回介于 [0,n) 之间的伪随机数。

你可以使用 rand.Seed(value) 函数来提供伪随机数的生成种子,一般情况下都会使用当前时间的纳秒级数字。

运算符与优先级

优先级     运算符
 7         ^ !
 6         * / % << >> & &^
 5         + - | ^
 4         == != < <= >= >
 3         <-
 2         &&
 1         ||

当然,也可以通过使用括号来临时提升某个表达式的整体运算优先级。

 类型别名

当你在使用某个类型时,你可以给它起另一个名字,然后你就可以在你的代码中使用新的名字(用于简化名称或解决名称冲突)。

在 type TZ int 中,TZ 就是 int 类型的新名称(用于表示程序中的时区),然后就可以使用 TZ 来操作 int 类型的数据。

示例 

package main
import "fmt"

type TZ int

func main() {
    var a, b TZ = 3, 4
    c := a + b
    fmt.Printf("c has the value: %d", c) // 输出:c has the value: 7
}

实际上,类型别名得到的新类型并非和原类型完全相同,新类型不会拥有原类型所附带的方法;TZ 可以自定义一个方法用来输出更加人性化的时区信息。

字符类型

严格来说,这并不是 Go 语言的一个类型,字符只是整数的特殊用例。byte 类型是 uint8 的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题。例如:var ch byte = 'A';字符使用单引号括起来。

在 ASCII 码表中,'A' 的值是 65,而使用 16 进制表示则为 41,所以下面的写法是等效的:

var ch byte = 65 或 var ch byte = '\x41'

\x 总是紧跟着长度为 2 的 16 进制数)

另外一种可能的写法是 \ 后面紧跟着长度为 3 的 8 进制数,例如:\377

不过 Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。其实 rune 也是 Go 当中的一个类型,并且是 int32 的别名。

在书写 Unicode 字符时,需要在 16 进制数之前加上前缀 \u 或者 \U

因为 Unicode 至少占用 2 个字节,所以我们使用 int16 或者 int 类型来表示。如果需要使用到 4 字节,则会加上 \U 前缀;前缀 \u 则总是紧跟着长度为 4 的 16 进制数,前缀 \U 紧跟着长度为 8 的 16 进制数。

示例

var ch int = '\u0041'
var ch2 int = '\u03B2'
var ch3 int = '\U00101234'
fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) // integer
fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) // character
fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) // UTF-8 bytes
fmt.Printf("%U - %U - %U", ch, ch2, ch3) // UTF-8 code point

输出

65 - 946 - 1053236
A - β - r
41 - 3B2 - 101234
U+0041 - U+03B2 - U+101234

格式化说明符 %c 用于表示字符;当和字符配合使用时,%v 或 %d 会输出用于表示该字符的整数;%U 输出格式为 U+hhhh 的字符串。

包 unicode 包含了一些针对测试字符的非常有用的函数(其中 ch 代表字符):

  • 判断是否为字母:unicode.IsLetter(ch)
  • 判断是否为数字:unicode.IsDigit(ch)
  • 判断是否为空白符号:unicode.IsSpace(ch)

这些函数返回单个布尔值。包 utf8 拥有更多与 rune 类型相关的函数

 

标签:语言,int,运算符,类型,使用,go,Go,true,布尔
From: https://www.cnblogs.com/songyunjie/p/17605669.html

相关文章

  • C语言.多级指针
    #include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){longaa=123;longaaa=&aa;//warning:initializationof‘longint’from‘longint*’makesintegerfrompointerwithoutacast//这里,编译器......
  • 指针进阶(C语言)
    指针进阶头文件#include<stdio.h>#include<stdlib.h>#include<string.h>字符指针intmain(){//字符指针chararr1[]="abcdef";chararr2[]="abcdef";char*p1="abcdef";char*p2="abcdef";......
  • 4 抽象工厂方法 -- go语言设计模式
    工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。因此,可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,这就是本文将要学习的......
  • linux上使用yum部署mongodb4.2+分片副本
    来源:https://blog.51cto.com/wutengfei/5937039系统配置Linux是有文件句柄限制的,而且默认不是很高,一般都是1024,作为一台生产服务器,其实很容易就达到这个数量。为防止服务因toomanyopenfiles错误出现宕机,这里需要对linux系统句柄数进行调整。##临时调整,系统重启即失效ulimit......
  • go语言基础-基础数据类型之常量
    常量使用关键字const定义,用于存储不会改变的数据。存储在常量中的数据类型只能是布尔型、数字型(整数型、浮点型和复数)和字符串型。常量的定义格式:constidentifier[type]=value,例如:constPi=3.14159在Go语言中,你可以省略类型说明符[type],因为编译器可以根据变量的值来......
  • go语言基础-语言的核心结构与技术之基本结构要素
    packagemainimport"fmt"funcmain(){fmt.Println("hello,world")}上述伪代码可以看到,学习go语言的基本语法,接下来,针对这段伪代码分析packagemain封装的概念,导入与可见性包是构造代码的一种方式:每个程序都由包(通常简称为pkg)的概念组成,可以使用自身的包或者......
  • Go - go get
    zzh@ZZHPC:~/zd/MyPrograms/Go/zapp10$gorunmain.gomain.go:6:5:norequiredmoduleprovidespackagegithub.com/XXX/zzhrepo1/calc;toaddit:gogetgithub.com/XXX/zzhrepo1/calczzh@ZZHPC:~/zd/MyPrograms/Go/zapp10$catgo.modmodulezapp10go1.2......
  • R语言改进关联规则挖掘Apriori在超市销售数据可视化
    全文链接:https://tecdat.cn/?p=33364原文出处:拓端数据部落公众号超市业已成为商业领域最具活力的商业业态,竞争也变得日益激烈。数据挖掘技术越来越多地服务于超市营销战略,本文在数据挖掘的基础上,深入分析了关联规则算法,研究算法的基本思想、算法的性质,并对算法进行详细的性能分......
  • C语言实现简易版扫雷
     扫雷作为一款内置于windowsXP系统的游戏,相信大多数人都有游玩过。接下来我将带着各位用C语言来实现这个游戏。首先,我们来了解扫雷游戏的规则,将这些规则逐步用函数来实现,再经过逻辑的调整即可得到所需的代码。可以试着先自己玩一把再继续看本文章。扫雷游戏网页版-Minesweeper......
  • Go语言
    GO语言深思熟虑之后决定先入门go折腾折腾,本来也犹豫不定,但是悠哥说的那句,年轻就是要去折腾.不管如何就先,开始着手去学习,而不是沉静在焦虑中..首先是GO的安装参考csdn上的https://blog.csdn.net/qq_44830881/article/details/123457805然而在我按照这个完成安装之后我运行hello......