当前位置 博文首页 > go类型转换及与C的类型转换方式

    go类型转换及与C的类型转换方式

    作者:this.Destroy() 时间:2021-05-26 18:02

    GO类型转换及与C的类型转换

    类型转换

    语法

    dst := float32(src)

    示例

    var num int = 520
    f32 := float32(num)
    i64 := int64(num)

    注意:加入val是一个指针,int32(val)相当于*(int32(var1)),指针不能直接转换成一个int32类型,应该改为(*int32)(var1),所以某些类型可能引起误会的应该用括号括起来转换。

    类型断言

    语法

    dst,ok := src.(int) // 安全类型断言,通过ok判断是否转换成功
    dst := src.(int)   // 非安全类型断言,无法确定是否转换成功

    示例

    var val interface{} = 123
    num,ok := val.(int)
    if ok {
        fmt.Printf("%T->%d\n", num, num)
    } else {
        fmt.Println("类型不匹配")
    }

    其他转换

    go提供了strconv包来进行转换

    bytes 、string转换

    //类型转换  string to bytes 
    func str2bytes(s string) []byte { 
        x := (*[2]uintptr)(unsafe.Pointer(&s)) 
        h := [3]uintptr{x[0], x[1], x[1]} 
        return *(*[]byte)(unsafe.Pointer(&h)) 
    }
    //类型转换  bytes to string 
    func bytes2str(b []byte) string { 
        return *(*string)(unsafe.Pointer(&b)) 
    }

    interface转为string

    //interface转为string 
    func interface2string(inter interface{}) string { 
        tempStr := "" 
        switch inter.(type) { 
            case string: tempStr = inter.(string) break 
            case float64: tempStr = strconv.FormatFloat(inter.(float64), 'f', -1, 64) break 
            case int64: tempStr = strconv.FormatInt(inter.(int64), 10) break 
            case int: tempStr = strconv.Itoa(inter.(int)) break 
     } 
        return tempStr 
    }
    //整形转字符串
    strconv.Itoa(100)
    //该方法的源码是:
    //可以看出是FormatInt方法的简单实现。
    func Itoa(i int) string {
            return FormatInt(int64(i), 10)
    }
    //字符串转整形
    i, _ := strconv.Atoi("100")
    //64位整形转字符串,FormatInt第二个参数表示进制,10表示十进制
    var i int64
    i = 0x100
    strconv.FormatInt(i, 10)
    //字节转32位整形
    b := []byte{0x00, 0x00, 0x03, 0xe8}
    bytesBuffer := bytes.NewBuffer(b)
    //其中binary.BigEndian表示字节序,相应的还有little endian。通俗的说法叫大端、小端。
    var x int32
    binary.Read(bytesBuffer, binary.BigEndian, &x)
    fmt.Println(x)
    //32位整形转字节
    var x int32
    x = 106
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, x)
    fmt.Println(bytesBuffer.Bytes())
    //字节转字符串
    fmt.Println(string([]byte{97, 98, 99, 100}))
    //字符串转字节
    fmt.Println([]byte("abcd")) 
    

    string与unicode字符互转

    //string-->unicode
    func Str2uft16ptr(str string)(p uintptr){//将字符串转为utf16指针
     e:=utf16.Encode([]rune(str))//转成unicode
     e=append(e, uint16(0))//添加末尾的0
     p=uintptr(unsafe.Pointer(&e[0]))//转成指针
     //p=uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str)))
     return
    }
    //unicode-->string
    func addbuf(buf []uint16,newcap int)(newbuf []uint16){
     newbuf=make([]uint16,newcap)
     copy(newbuf,buf)
     return
    }
    func Utf16prt2str(p uintptr)(str string){//将utf16指针转为字符串
     len:=0
     buf:=make([]uint16,64)
     for a:=(*(*uint16)(unsafe.Pointer(p)));a!=0;len++{
      if len>=cap(buf){
       buf=addbuf(buf,len*2)
      }
      buf[len]=a
      p+=2//uint16占2字节
      a=(*(*uint16)(unsafe.Pointer(p)))
     }
     str=string(utf16.Decode(buf[:len]))
     return
    }
    

    go和c类型装换

    #cgo
    char -->  C.char -->  byte
    signed char -->  C.schar -->  int8
    unsigned char -->  C.uchar -->  uint8
    short int -->  C.short -->  int16
    short unsigned int -->  C.ushort -->  uint16
    int -->  C.int -->  int
    unsigned int -->  C.uint -->  uint32
    long int -->  C.long -->  int32 or int64
    long unsigned int -->  C.ulong -->  uint32 or uint64
    long long int -->  C.longlong -->  int64
    long long unsigned int -->  C.ulonglong -->  uint64
    float -->  C.float -->  float32
    double -->  C.double -->  float64
    wchar_t -->  C.wchar_t  -->  
    void * -> unsafe.Pointer
    #window
    uint64 //对应SIZE_T
    uint32 //对应DWORD
    
    //整型数
    //Go->C:
    var i int
    ci := C.int(i)
    //C->Go:
    var i C.int
    goi := int(i)
    //数组和字符串
    //Go->C:
    var str string
    cstr := C.CString(str)
    //C->Go:
    /*
    #include <stdlib.h>
    #include <stdio.h>
    char foo[] = "hellofoo";
    char *bar = "hellobar";
    */
    import "C"
    import "fmt"
    func main() {
        fmt.Printf("%s\n", C.GoString(&C.foo[0]))
        fmt.Printf("%s\n", C.GoString(C.bar))
    }
    //数组类型转换
    /*
    #include <stdio.h>
    int cIArray[] = {1, 2, 3, 4, 5, 6, 7}; //int
    float cFArray[] = {1.011, 2.022, 3.022, 4.023, 5.02, 6.03, 7.045};//float
    */
    import "C"
    import "fmt"
    func main() {
        goIArray := C.cIArray[:]
        fmt.Println(goIArray)
        goFArray := C.cFArray[:]
        fmt.Println(goFArray)
    }
    //[]byte 转换为 *char
    c_char := (*C.char)(unsafe.Pointer(&bt[0]))
    

    fmt格式字符串:

    打印格式 含义
    %% 一个%字面量
    %b 一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数
    %c 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符
    %d 一个十进制数值(基数为10)
    %e 以科学记数法e表示的浮点数或者复数值
    %E 以科学记数法E表示的浮点数或者复数值
    %f 以标准记数法表示的浮点数或者复数值
    %g 以%e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
    %G 以%E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
    %o 一个以八进制表示的数字(基数为8)
    %p 以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示
    %q 使用Go语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字
    %s 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符)
    %t 以true或者false输出的布尔值
    %T 使用Go语法输出的值的类型
    %U 一个用Unicode表示法表示的整型码点,默认值为4个数字字符
    %v 使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话
    %x 以十六进制表示的整型值(基数为十六),数字a-f使用小写表示
    %X 以十六进制表示的整型值(基数为十六),数字A-F使用小写表示
    强制转换 隐式转换 类型断言
    类型之间 可以 不可以 可以
    类型->接口 可以 可以 可以
    接口->类型 不可以 不可以 可以
    接口之间 可以(编译期间确定) 可以(编译期间确定) 可以

    补充:Golang常见类型转换

    1.Type(expression):

    int(time.Now().Weekday()) //星期转int
    int(time.Now().Month())   //月份转int
    var a float64
    a = 3.1
    b := int(a) //float64转int
    var a int
    a = 1
    b := int64(a) //int转int64

    2.strconv包:

    string和int、int32、int64:

    i, _ := strconv.Atoi(s) //string转int
    s := strconv.Itoa(i)    //int转string
    i, _ := strconv.ParseInt(s, 10, 32) //string转int32
    ii := int32(I)
    i, _ := strconv.ParseInt(s, 10, 64) //string转int32
    s := strconv.FormatInt(i, 10)       //int64转string

    ParseInt函数的官方介绍:

    func ParseInt(s string, base int, bitSize int) (i int64, err error)

    –返回字符串表示的整数值,接受正负号。

    –base指定进制(2到36),如果base为0,则会从字符串前置判断,"0x"是16进制,"0"是8进制,否则是10进制。

    –bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64。

    –返回的err是*NumErr类型的,如果语法有误,err.Error = ErrSyntax;如果结果超出类型范围err.Error = ErrRange。

    FormatInt函数中的10,表示10进制。

    string和float32、float64:

    f, _ := strconv.ParseFloat(s, 32)        //string转float32
    ff := float32(f)
    f, _ := strconv.ParseFloat(s, 64)        //string转float64
    s := strconv.FormatFloat(f, 'f', -1, 64) //float64转string

    ParseFloat函数的官方介绍:

    func ParseFloat(s string, bitSize int) (f float64, err error)

    –解析一个表示浮点数的字符串并返回其值。

    –如果s合乎语法规则,函数会返回最为接近s表示值的一个浮点数(使用IEEE754规范舍入)。

    –bitSize指定了期望的接收类型,32是float32(返回值可以不改变精确值的赋值给float32),64是float64。

    –返回值err是*NumErr类型的,语法有误的,err.Error=ErrSyntax;结果超出表示范围的,返回值f为±Inf,err.Error= ErrRange。

    FormatFloat函数的官方介绍:

    func FormatFloat(f float64, fmt byte, prec, bitSize int) string

    –bitSize表示f的来源类型(32:float32、64:float64),会据此进行舍入。

    –fmt表示格式:‘f'(-ddd.dddd)、‘b'(-ddddp±ddd,指数为二进制)、‘e'(-d.dddde±dd,十进制指数)、‘E'(-d.ddddE±dd,十进制指数)、‘g'(指数很大时用'e'格式,否则'f'格式)、‘G'(指数很大时用'E'格式,否则'f'格式)。

    –prec控制精度(排除指数部分):对'f'、‘e'、‘E',它表示小数点后的数字个数;对'g'、‘G',它控制总的数字个数。如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。

    string和time:

    t, _ := time.Parse("2006-01-02 15:04:05", s) //string转时间
    t, _ := time.ParseInLocation("2006-01-02 15:04:05", s, time.Local) //string转本地时间
    s := t.Format("2006-01-02 15:04:05")         //时间转string

    3.类型断言:expression.(Type):

    expression必须是接口类型,且自身类型与Type类型相符。

    expression.(Type)的返回值一般为两个:value和ok,匹配成功ok为true,value有值,匹配失败ok为false,value无值;也可以直接接受value一个返回值,不过失败则直接panic:

    func main() {
      var a interface{} = 100
      if aa, ok := a.(int); ok {
        fmt.Println(aa)
      }
    }

    还可以结合switch和case使用,来判断接口实际类型:

    func main() {
      var t interface{} = 100
      switch i := t.(type) {
      case float32:
        fmt.Printf("i的类型%T i的值%v\n", i, i)
      case float64:
        fmt.Printf("i的类型%T i的值%v\n", i, i)
      case int:
        fmt.Printf("i的类型%T i的值%v\n", i, i)
      case bool:
        fmt.Printf("i的类型%T i的值%v\n", i, i)
      case string:
        fmt.Printf("i的类型%T i的值%v\n", i, i)
      default:
        fmt.Println("其他类型")
      }
    }

    4.JSON:

    Golang中大多数数据类型都可以转化为有效的JSON文本,除了channel通道、complex复数、func函数等。

    Golang指针可进行隐式转换,表面进行的是指针序列化,内部会针对指针进行取值操作,实际还是针对所指的对象进行序列化。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持站长博客。如有错误或未考虑完全的地方,望不吝赐教。

    js