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

类型转换

语法

1
dst := float32(src)

示例

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

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

类型断言

语法

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

示例

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

其他转换

go提供了 strconv 包来进行转换

bytes 、string转换

1
2
3
4
5
6
7
8
9
10
//类型转换  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

1
2
3
4
5
6
7
8
9
10
11
//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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//整形转字符串
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字符互转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//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类型装换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//整型数
//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使用小写表示

| 强制转换 | 隐式转换 | 类型断言 |
|:--------- | :---------- | :---------- | :----|
|类型之间 | 可以 | 不可以 | 可以|
|类型->接口 | 可以 | 可以 | 可以|
|接口->类型 | 不可以 | 不可以 | 可以|
|接口之间 | 可以(编译期间确定) | 可以(编译期间确定) | 可以|