GO類型轉換及與C的類型轉換
類型轉換
語法
示例
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指針可進行隱式轉換,表面進行的是指針序列化,內部會針對指針進行取值操作,實際還是針對所指的對象進行序列化。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
您可能感興趣的文章:- go 類型轉換方式(interface 類型的轉換)
- Go語言strconv包實現字符串和數值類型的相互轉換
- golang類型轉換組件Cast的使用詳解
- Golang中的自定義類型之間的轉換的實現(type conversion)