Go语言基础--数据类型相互转换、指针

数据类型默认值

  1. 布尔类型(bool)false

  2. 整型(int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64)0

  3. 浮点型(float32、float64)0.0

  4. 复数类型(complex64、complex128)(0+0i),其中i是虚数单位

  5. 字符串(string):空字符串""

  6. 字节切片([]byte)nil,但如果是作为结构体字段或数组元素,则会被初始化为长度为0的切片(即[]byte{},但注意这仅适用于全局变量或结构体字段的自动初始化,局部变量仍会是nil

  7. 其他切片(如[]intnil,但同样,如果作为结构体字段或数组元素,则会被初始化为长度为0的切片(如[]int{}

  8. 映射(map)nil

  9. 通道(chan)nil

  10. 接口(interface{})nil

  11. 结构体(struct):结构体中每个字段都会被初始化为该字段类型的零值。如果结构体包含其他结构体或指针等,这些也会被递归地初始化为它们的零值。

  12. 指针(*T)nil,其中T是任意类型

  13. 函数(func):函数类型没有零值的概念,因为函数不是变量,而是可以被调用的代码块。但是,函数类型的变量(即函数指针)的零值是nil。

 基本数据类型相互转换

        基本数据类型转string

                fmt.Sprintf("%参数", 表达式)     会返回转换后的字符串

package main

import (

    "fmt"

    _"strconv"

)  

func main() {  

    i := 123  

    s := fmt.Sprintf("%d", i) // 将int转换为string  

    fmt.Println(s, "is a string")  

    fmt.Printf("s的数据类型为%T s=%q\n",s,s)

    f := 3.14  

    sf := fmt.Sprintf("%.2f", f) // 将float64转换为带两位小数的string  

    fmt.Println(sf, "is a string")  

    fmt.Printf("sf的数据类型为%T sf=%q\n",sf,sf)

    c := 'A'  

    sc := fmt.Sprintf("%c", c) // 将rune(在Go中char实际上是rune类型)转换为string  

    fmt.Println(sc, "is a string")

    fmt.Printf("sc的数据类型为%T sc=%q\n",sc,sc)

    // 注意:bool类型通常不直接转换为string,但可以通过fmt.Sprintf实现  

    b := true  

    sb := fmt.Sprintf("%t", b) // 将bool转换为string  

    fmt.Println(sb, "is a string")  

    fmt.Printf("sb的数据类型为%T sb=%q\n",sb,sb)

}

使用strconv

对于整数和浮点数,strconv包提供了Itoa(int to ASCII)和FormatFloat等函数,但请注意Itoa只适用于int类型。对于其他整数类型(如int64),你可能需要使用FormatInt

package main  

import (  

    "fmt"  

    "strconv"  

)  

func main() {  

    i := 123  

    s := strconv.Itoa(i) // 将int转换为string  

    fmt.Println(s, "is a string")  

    i64 := int64(1234567890)  

    s64 := strconv.FormatInt(i64, 10) // 将int64转换为string,10表示十进制  

    fmt.Println(s64, "is a string")  

    // 注意:对于float64,strconv.FormatFloat是更通用的选择  

    f := 3.14  

    sf := strconv.FormatFloat(f, 'f', -1, 64) // 'f'表示固定点数表示,-1表示精度(自动),64表示float64  

    fmt.Println(sf, "is a string")  

}

 

string转基本数据类型

        使用strconv

        strconv包提供了ParseIntParseUintParseFloatParseBool等函数,用于将string转换为相应的基本数据类型。

package main  

import (  

    "fmt"  

    "strconv"  

)  

func main() {  

    s := "123"  

    i, err := strconv.Atoi(s) // Atoi是ParseInt的简便封装,只处理int类型  

    if err != nil {  

        fmt.Println("Error converting string to int:", err)  

    }  

    fmt.Println(i, "is an int")  

    s64 := "1234567890"  

    i64, err := strconv.ParseInt(s64, 10, 64) // 第二个参数是基数(10表示十进制),第三个参数是bitSize  

    if err != nil {  

        fmt.Println("Error converting string to int64:", err)  

    }  

    fmt.Println(i64, "is an int64")  

    sf := "3.14"  

    f, err := strconv.ParseFloat(sf, 64) // 第二个参数是bitSize(32或64)  

    if err != nil {  

        fmt.Println("Error converting string to float64:", err)  

    }  

    fmt.Println(f, "is a float64")  

    sb := "true"  

    b, err := strconv.ParseBool(sb)  

    if err != nil {  

        fmt.Println("Error converting string to bool:", err)  

    }  

    fmt.Println(b, "is a bool")  

}

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

对于’%‘的解释:

        在Go语言的fmt.Sprintf函数中,%后跟的字母称为格式说明符(format specifier),它们决定了如何将后续的值(参数)格式化为字符串。每个格式说明符都对应一种不同的数据类型或值的表示方式。在你给出的例子中,%d%.2f%c%t分别代表了不同的数据类型或值的格式化方式:

  1. %d:用于整数(intint8int16int32int64 等)的十进制表示。它会把整数转换成其十进制形式的字符串。

  2. %.2f:用于浮点数(float32float64)的格式化表示,其中.2指定了小数点后的位数,即保留两位小数。它会把浮点数转换成具有两位小数的字符串。

  3. %c:用于字符(在Go中实际上是rune类型,用于表示Unicode字符)的格式化。它会把rune类型的值转换成对应的单个字符的字符串。

  4. %t:用于布尔值(bool)的格式化。它会把布尔值转换成字符串"true"或"false"。

        这些格式说明符允许开发者在将值转换为字符串时,指定值的表示形式,比如整数是否以十六进制显示、浮点数保留多少位小数、字符是否应该直接显示等。这种灵活性是fmt包提供的重要特性之一,使得在输出格式化字符串时非常方便。

        在fmt.Printffmt.Sprintf等函数中,这些格式说明符都是通用的,可以用于任何需要格式化输出的场景。不过,需要注意的是,格式说明符必须与它后面的参数类型相匹配,否则可能会导致运行时错误或不符合预期的输出。例如,你尝试用%d来格式化一个浮点数,结果可能不是你想要的。

 

指针变量

        想象一下,每个变量在计算机的内存中都有一个独特的“家”(地址)。指针就像是那个“家”的门牌号,但它不是直接存储数据,而是存储了数据所在的“家”的地址。通过指针,我们可以直接找到并操作那个“家”里的数据,而不需要复制数据本身。

指针变量的声明和初始化

        在Go语言中,我们可以通过在变量类型前加上*符号来声明一个指针变量。例如,var ptr *int声明了一个名为ptr的指针变量,它可以指向一个int类型的变量。

初始化指针变量通常有两种方式:

  1. 使用&操作符&操作符可以获取一个变量的地址,并将这个地址赋值给指针变量。例如,var a int = 10; ptr = &a;这样,ptr就指向了a的地址。

  2. 使用new函数new函数是Go语言内建的一个函数,用于为指定类型分配内存,并返回指向这块内存的指针。例如,ptr = new(int)会为int类型分配内存,并将返回的指针赋值给ptr。

指针的使用

指针的使用主要涉及两个操作符:&(取地址)和*(解引用,即根据地址取值)。

  • 取地址:如上所述,使用&操作符可以获取变量的地址。

  • 解引用:使用*操作符可以获取指针所指向的变量的值。例如,如果ptr指向了a的地址,那么*ptr就等价于a的值。

例子:

package main

import(

    "fmt"

)

func main(){

    var a int =123

    var str string = "forword"

    fmt.Printf("a: %p, str:%p",&a,&str)

}

 a: 0xc00000a0e8, str:0xc000026070

内存地址是0x十六进制前缀的一组数据

    var ptr *int =&b

    fmt.Printf("ptr地址=%v\n",&ptr)

    fmt.Printf("b的地址=%v\n",ptr)

    fmt.Printf("ptr值=%v\n",*ptr)

 

b的地址为 0xc00000a108

ptr地址=0xc000058030

ptr=0xc00000a108

ptr值=1234

指针的重要性

指针在Go语言中非常重要,原因有以下几点:

  1. 提高效率:通过指针,我们可以直接操作内存中的数据,避免了数据复制的开销,这在处理大型数据结构时尤为重要。

  2. 实现引用传递:在Go语言中,函数的参数传递默认是值传递。但如果我们传递的是指针,那么在函数内部对指针所指向的变量的修改会影响到原始变量。

  3. 实现动态数据结构:如切片(slice)、映射(map)和通道(channel)等Go语言中的高级数据结构,在底层都是通过指针来实现的。

注意事项

虽然指针很强大,但也需要谨慎使用,以避免出现以下问题:

  • 空指针解引用:如果指针没有被正确初始化(即它指向的是nil),那么尝试解引用它将导致运行时错误。

  • 悬挂指针:如果指针指向的内存被释放或重新分配,但指针本身没有被更新,那么这个指针就变成了悬挂指针,解引用它也可能导致错误。

  • 内存泄漏:如果不再需要某个指针指向的内存,但没有显式地释放它(Go语言有垃圾回收机制,但在某些情况下仍需注意),就可能导致内存泄漏。

        

 

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值