2014-10-17 18 views
6

Người mới bắt đầu Lập trình viên ở đây. Tôi có một nhu cầu để nhân đôi lát (và một phần của mảng cơ bản) để một người gọi sẽ không đột biến các yếu tố ban đầu của một mảng. Tôi nghĩ rằng tôi có thể viết một hàm để thực hiện việc này cho các mảng các loại cụ thể:Cách chung để sao chép Go lát?

func duplicateSliceOfSomeType(sliceOfSomeType []SomeType) []SomeType { 
    dulicate := make([]SomeType, len(sliceOfSomeType)) 
    copy(duplicate, sliceOfSomeType) 
    return duplicate 
} 

Nhưng có cách nào để tạo ra cùng một phương pháp chung, có lẽ không có generics?

func duplicateSlice(slice []?) []?{ 
    duplicate := make([]?, len(slice)) 
    copy(duplicate, slice) 
    return duplicate 
} 

Trả lời

20

Bạn có thể viết một câu lệnh đơn giản để tạo một bản sao cạn của một lát,

b := append([]T(nil), a...) 

Đó là tương đương với,

b := make([]T, len(a)) 
copy(b, a) 

Ví dụ,

package main 

import "fmt" 

type T int 

func main() { 
    a := []T{4, 2} 

    b := append([]T(nil), a...) 

    fmt.Println(&a[0], a, &b[0], b) 
    b[0] = 9 
    fmt.Println(&a[0], a, &b[0], b) 
} 

Đầu ra:

0x10328000 [4 2] 0x10328020 [4 2] 
0x10328000 [4 2] 0x10328020 [9 2] 

PHỤ LỤC:

Common difficulties with reflection

Nếu người dân chưa quen to Go, họ không nên sử dụng phản chiếu ở tất cả.

-rob

Phản ánh là tinh tế ngay cả đối với các chuyên gia. Nó cho thấy chi tiết có sự hiểu biết của phụ thuộc vào việc biết những điều khá cơ bản về cách thức hoạt động của ngôn ngữ và mức độ thấp hơn, cách thức hoạt động của ngôn ngữ đó. Nó có thể gây bối rối ngay cả đối với các lập trình viên có kinh nghiệm về Go; cho mới Gophers đúc có nhiều điều quan trọng hơn, đơn giản hơn để tìm hiểu trước tiên. Những người tìm hiểu sự phản chiếu quá sớm lẫn lộn đám mây của họ sự hiểu biết của họ về những nguyên tắc cơ bản đó. Tốt nhất để giữ nó ở độ dài của cánh tay cho đến khi phần còn lại của hình ảnh rõ ràng.

-rob

Điều đó nói rằng,

package main 

import (
    "fmt" 
    "reflect" 
) 

func CopySlice(s interface{}) interface{} { 
    t, v := reflect.TypeOf(s), reflect.ValueOf(s) 
    c := reflect.MakeSlice(t, v.Len(), v.Len()) 
    reflect.Copy(c, v) 
    return c.Interface() 
} 

type T int 

func main() { 

    { 
     // append 
     a := []T{4, 2} 
     b := append([]T(nil), a...) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // make and copy 
     a := []T{4, 2} 
     b := make([]T, len(a)) 
     copy(b, a) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // reflection 
     a := []T{4, 2} 
     b := CopySlice(a).([]T) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

} 

Output:

0xc20800a200 [4 2] 0xc20800a210 [4 2] 
0xc20800a200 [4 2] 0xc20800a210 [9 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [4 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [9 2] 
0xc20800a310 [4 2] 0xc20800a320 [4 2] 
0xc20800a310 [4 2] 0xc20800a320 [9 2] 
+0

Vì vậy, về bản chất bạn đang chắp thêm các phần tử 'a' vào một lát mới, trống cho một mảng mới được gán cho' b', đúng không? – Kaiged

+0

Phương thức 'append' có phải là phương thức' make'/'copy' không? – Kaiged

+0

@Kaiged: Nối thêm một 'nil' slice sẽ dịch thành' make' và 'copy'. Xem câu trả lời đã sửa đổi của tôi. – peterSO

0

Bạn có thể làm một bản sao trên bất kỳ loại bằng cách sử dụng các gói reflect, cụ thể reflect.Copy: http://golang.org/pkg/reflect/#Copy

+0

Tôi muốn xem một ví dụ cụ thể về điều này. – Kaiged

Các vấn đề liên quan