Khai báo một mảng không đổi


164

Tôi đã thử:

const ascii = "abcdefghijklmnopqrstuvwxyz"
const letter_goodness []float32  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness = []float32 { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }

Đầu tiên, khai báo và khởi tạo hoạt động tốt, nhưng thứ hai, thứ ba và thứ tư không hoạt động. Làm thế nào tôi có thể khai báo và khởi tạo mảng const của float?

Câu trả lời:


232

Một mảng không phải là bất biến của tự nhiên; bạn không thể làm cho nó liên tục.

Gần nhất bạn có thể nhận được là:

var letter_goodness = [...]float32 {.0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }

Lưu ý [...]thay vì []: nó đảm bảo bạn có được một mảng (kích thước cố định) thay vì một lát. Vì vậy, các giá trị không cố định nhưng kích thước là.


126
Chỉ cần làm rõ: [...]Tcú pháp là đường cho [123]T. Nó tạo ra một mảng kích thước cố định, nhưng cho phép trình biên dịch tìm ra có bao nhiêu phần tử trong đó.
jimt

5
Tôi đoán cho phép các mảng không đổi sẽ yêu cầu cập nhật cho hệ thống loại. Mặt khác, nếu bạn đã xác định một hàm f(xs [5]int)bạn sẽ không biết nếu mảng được truyền là không đổi hoặc có thể thay đổi.
Thomas Ahle

tks, tôi có vấn đề khi tôi cố gắng xâu chuỗi.Join cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
Eddy Hernandez

Cảm ơn các giải pháp lát. Nghi ngờ: một mảng chính nó là bất biến, phải không? Người ta không thể thêm hoặc xóa các thành phần sau khi một mảng được tạo, phải không? Tôi có thể, tuy nhiên, chỉnh sửa các yếu tố mảng.
huyền thoại2k

@ legends2k Bạn không thể thay đổi kích thước của mảng, vâng, nhưng bạn có thể đặt các giá trị khác vào vị trí của nó.
Denys Séguret

63

Từ đi hiệu quả :

Các hằng số trong Go chỉ là hằng số mà. Chúng được tạo ra tại thời gian biên dịch, ngay cả khi được định nghĩa là các hàm cục bộ trong các hàm và chỉ có thể là số, chuỗi hoặc booleans. Do hạn chế thời gian biên dịch, các biểu thức xác định chúng phải là biểu thức không đổi, được trình biên dịch đánh giá. Chẳng hạn, 1 << 3 là một biểu thức không đổi, trong khi math.Sin (math.Pi / 4) không phải vì hàm gọi tới math.Sin cần xảy ra trong thời gian chạy.

Các lát và mảng luôn được đánh giá trong thời gian chạy:

var TestSlice = []float32 {.03, .02}
var TestArray = [2]float32 {.03, .02}
var TestArray2 = [...]float32 {.03, .02}

[...]báo cho trình biên dịch tìm ra chiều dài của chính mảng đó. Các lát cắt mảng và dễ dàng hơn để làm việc với hầu hết các trường hợp. Thay vì sử dụng hằng, chỉ làm cho các biến không thể truy cập được đến các gói khác bằng cách sử dụng chữ cái đầu tiên viết thường:

var ThisIsPublic = [2]float32 {.03, .02}
var thisIsPrivate = [2]float32 {.03, .02}

thisIsPrivatechỉ có sẵn trong gói nó được xác định. Nếu bạn cần truy cập đọc từ bên ngoài, bạn có thể viết một hàm getter đơn giản (xem Getters trong golang ).


12

Không có thứ gọi là hằng số mảng trong Go.

Trích dẫn từ Đặc tả ngôn ngữ Go: Hằng số :

hằng boolean , hằng rune , hằng số nguyên , hằng dấu chấm động , hằng phức tạp , và hằng chuỗi . Các hằng số Rune, số nguyên, dấu phẩy động và phức được gọi chung là các hằng số .

Một biểu hiện liên tục (được sử dụng để khởi tạo một hằng số) có thể chứa chỉ liên tục toán hạng và được đánh giá tại thời gian biên dịch.

Các đặc điểm kỹ thuật liệt kê các loại hằng số khác nhau. Lưu ý rằng bạn có thể tạo và khởi tạo các hằng với các biểu thức không đổi của các loại có một trong các loại được phép làm loại cơ bản . Ví dụ: điều này là hợp lệ:

func main() {
    type Myint int
    const i1 Myint = 1
    const i2 = Myint(2)
    fmt.Printf("%T %v\n", i1, i1)
    fmt.Printf("%T %v\n", i2, i2)
}

Đầu ra (thử trên Sân chơi Go ):

main.Myint 1
main.Myint 2

Nếu bạn cần một mảng, nó chỉ có thể là một biến, nhưng không phải là hằng số.

Tôi giới thiệu bài viết blog tuyệt vời này về hằng số: Hằng số


Sau đó, làm gì nếu cần một container với kích thước không đổi?

@Atomic_alarm Bạn có thể giải thích rõ hơn không?
icza

Tồn tại liệu trong mảng C tương tự golang?

@Atomic_alarm Có, mảng cũng tồn tại trong Go, chúng không phải là biểu thức không đổi, chúng được đánh giá khi chạy. Vì vậy, một hằng số không thể là một kiểu mảng, nhưng một biến có thể. Ví dụ:var arr = [2]int{2, 3}
icza

3

Như những người khác đã đề cập, không có cấu trúc Go chính thức cho việc này. Gần nhất tôi có thể tưởng tượng sẽ là một hàm trả về một lát. Theo cách này, bạn có thể đảm bảo rằng không ai sẽ thao túng các phần tử của lát gốc (vì nó được "mã hóa cứng" vào mảng).

Tôi đã rút ngắn lát cắt của bạn để làm cho nó ... ngắn hơn ...:

func GetLetterGoodness() []float32 {
    return [...]float32 { .0817,.0149,.0278,.0425,.1270,.0223 }
}

4
điều này nghe có vẻ là cách tốt nhất để đi, tuy nhiên kiểu trả về func không khớp. cannot use [6]string literal (type [6]string) as type []string in return argumentvì vậyreturn []float32 { ... }
theRemix

@theRemix Ba cách khắc phục có thể: (1) xóa ...để khai báo một lát bằng chữ thay vì một mảng bằng chữ. (2) thay đổi kiểu trả về thành [6]float32. (3) gán biểu thức cho một biến mảng a := [...]float32 { (etc.) }và trả về lát của tất cả các phần tử : return a[:]. (Mảng chữ không thể đánh địa chỉ, tôi không rõ tại sao.)
David Moles

Tôi không chắc những gì bạn đảm bảo. Có vẻ như bạn cố gắng giải quyết một cái gì đó trong mã của bạn có thể được giải quyết tốt hơn với các bài kiểm tra (đơn vị-).
Dynom
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.