欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-17 16:18:57
go类型转换及与c的类型转换类型转换语法dst := float32(src)示例var num int = 520f32 := float32(num)i64 := int64(num)注意:加入v...

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指针可进行隐式转换,表面进行的是指针序列化,内部会针对指针进行取值操作,实际还是针对所指的对象进行序列化。

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