Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Penukaran jenis kepingan dalam Go

Penukaran jenis kepingan dalam Go

WBOY
WBOYke hadapan
2024-02-10 15:00:20580semak imbas

Go 中的切片类型转换

editor php Apple memperkenalkan anda kepada penukaran jenis slice dalam bahasa Go. Dalam bahasa Go, slice ialah tatasusunan dinamik yang sering digunakan untuk menyimpan dan mengendalikan sekumpulan elemen daripada jenis yang sama. Penukaran jenis kepingan merujuk kepada menukar satu jenis kepingan kepada jenis kepingan lain, yang sangat biasa dalam pembangunan sebenar. Artikel ini akan memperkenalkan secara terperinci pertimbangan dan aplikasi praktikal penukaran jenis kepingan untuk membantu pembaca memahami dan menggunakan ciri ini dengan lebih baik.

Kandungan soalan

Saya sangat baru pergi, mempunyai latar belakang c++ dan terjumpa beberapa isu pelik. Kodnya adalah seperti berikut:

package main

import (
"fmt"
"unsafe"
)

func main() {
     arr := []string { "one", "two", "three" }
     address := unsafe.pointer(&arr)
     addptr := (*[]string)(unsafe.pointer(*(*uintptr)(address)))
     fmt.println((*addptr)[0])
}

Kod ini gagal dengan:

runtime error: growslice: len out of range

Sebagai contoh, jika saya menukar pelakon kepada:

addptr := (*[0]string)(unsafe.pointer(*(*uintptr)(address)))

Kod di atas berfungsi dengan baik.

Saya tahu ini adalah hantaran kepada penuding tatasusunan dan tatasusunan mesti mempunyai saiz yang tetap, Tetapi bagaimana saya menukarnya kepada penunjuk kepada kepingan?

Untuk menjadikan perkara lebih mengelirukan, anda boleh mendapatkan alamat hirisan dan menetapkannya kepada penunjuk seperti ini:

func main() {
     arr := []string { "one", "two", "three" }
     var arrPtr *[]string = &arr
     fmt.Println((*arrPtr)[0])
}

Semuanya akan berfungsi dengan baik kali ini, walaupun penunjuk adalah jenis yang sama yang saya hantarkan penunjuk tidak selamat pada contoh pertama. Bolehkah sesiapa membantu memahami apa sebenarnya yang berlaku di sini?

Penyelesaian

Sesetengah latar belakang: Pengepala kepingan mengandungi penunjuk kepada tatasusunan, panjang dan kapasiti sandaran.

Kod dalam bahagian pertama soalan menukarkan pengepala hirisan menjadi penuding kepada pengepala hirisan. go vet Arahan memberi amaran bahawa kod dalam soalan mungkin menyalahgunakan penunjuk yang tidak selamat.

Dibetulkan dengan mengalih keluar operasi penyahrujukan tambahan supaya kod bertukar daripada penuding kepada pengepala hirisan kepada penuding kepada pengepala hirisan.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer((*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one

Tidak perlu tukar ke *uintptr. Dipermudahkan kepada:

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer(address))
fmt.println((*addptr)[0]) // prints one

Tiada gurauan yang tidak selamat diperlukan. Dipermudahkan kepada:

arr := []string{"one", "two", "three"}
addptr := &arr
fmt.println((*addptr)[0]) // prints one

Gunakan kod berikut untuk menukar penuding tatasusunan sandaran kepingan kepada penuding tatasusunan. Kod ini rapuh kerana ia menganggap perkataan pertama pengepala hirisan ialah penunjuk kepada tatasusunan sandaran.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[1]string)(unsafe.pointer(*(*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one

Penukaran uintptr dalam coretan kod sebelumnya tidak diperlukan. Dipermudahkan kepada:

arr := []string{"one", "two", "three"}
address := unsafe.Pointer(&arr)
addPtr := (*[]string)(address)
fmt.Println((*addPtr)[0]) // prints one

Saya harap ini membantu.

Atas ialah kandungan terperinci Penukaran jenis kepingan dalam Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam
Artikel sebelumnya:Pergi Bina padamkan maklumatArtikel seterusnya:Pergi Bina padamkan maklumat