Rumah >pembangunan bahagian belakang >Golang >Pergi |. Cara yang cekap dan boleh dibaca untuk menambahkan kepingan dan menghantar ke fungsi variadic
Andaikan saya mempunyai saluran paip berfungsi berikut:
func func3(opts ...functionobject) { for _, opt := range opts { opt() } } func func2(opts ...functionobject) { var functions []functionobject functions = append(functions, somefunction3) functions = append(functions, somefunction4) ... ... ... func3(append(functions, opts...)...) } func func1(opts ...functionobject) { var functions []functionobject functions = append(functions, somefunction) functions = append(functions, somefunction2) ... ... ... func2(append(functions, opts...)...) }
Oleh kerana masalah yang saya ingin selesaikan adalah diwarisi, functions
中的函数应该在 opts
中的函数之前调用,所以我不能只附加到 opts
但我必须前置 functions
到opts
(通过 append(functions, opts...)
),然后再次使用 ...
menghantarnya ke fungsi seterusnya dalam perancangan, jadi saya mendapat ungkapan pelik:
func2(append(functions, opts...)...)
Saya tidak tahu betapa cekapnya, tetapi saya pasti ia kelihatan pelik,
Mesti ada cara yang lebih baik untuk melakukan ini, itulah yang saya cari. p>
Tetapi saya akan menghargai penjelasan yang disertakan tentang kecekapan :)
Sunting:
Saya tidak boleh menukar jenis parameter daripada opts ...functionobject
更改为 opts []functionobject
(如@dev.bmax 在评论中建议的那样),因为我在现有代码库中进行了更改,所以我无法更改调用 func{ 的函数1,2,3}
Tambah di hadapan kepingan pada dasarnya tidak cekap kerana ia memerlukan gabungan:
Adalah lebih cekap jika anda boleh menukar konvensyen panggilan antara fungsi untuk hanya menambah pilihan dan kemudian memprosesnya secara terbalik. Ini mengelakkan berulang kali mengalihkan item ke hujung kepingan dan mengelakkan semua kecuali peruntukan pertama (jika ruang yang mencukupi diperuntukkan lebih awal daripada masa).
func func3(opts ...functionobject) { for i := len(opts) - 1; i >= 0; i-- { opts[i]() } }
Nota: func3(opts ...functionobject) / func3(opts...)
和 func3(opts []functionobject) / func3(opts)
adalah setara dalam prestasi. Yang pertama adalah gula sintaksis yang berkesan untuk memotong kepingan.
Namun, anda menyebut bahawa anda perlu mengekalkan konvensyen panggilan...
Kod contoh anda akan menghasilkan pertama, kedua, ketiga, kelima... peruntukan tambahan dalam setiap fungsi - peruntukan diperlukan untuk menggandakan saiz tatasusunan sandaran (untuk kepingan kecil). append(functions, opts...)
juga boleh diperuntukkan jika lampiran awal tidak menghasilkan kapasiti ganti yang mencukupi.
Fungsi pembantu boleh menjadikan kod lebih mudah dibaca. Ia juga boleh diguna semula opts
Menyokong kapasiti ganti dalam tatasusunan:
func func2(opts ...functionobject) { // 1-2 allocations. always allocate the variadic slice containings // prepend items. prepend reallocates the backing array for `opts` // if needed. opts = prepend(opts, somefunction3, somefunction4) func3(opts...) } // generics requires go1.18+. otherwise change t to functionobject. func prepend[t any](base []t, items ...t) []t { if size := len(items) + len(base); size <= cap(base) { // extend base using spare slice capacity. out := base[:size] // move elements from the start to the end of the slice (handles overlaps). copy(out[len(items):], base) // copy prepended elements. copy(out, items) return out } return append(items, base...) // always re-allocate. }
Beberapa alternatif tanpa fungsi pembantu untuk menerangkan peruntukan dengan lebih terperinci:
// Directly allocate the items to prepend (2 allocations). func func1(opts ...FunctionObject) { // Allocate slice to prepend with no spare capacity, then append re-allocates the backing array // since it is not large enough for the additional `opts`. // In future, Go could allocate enough space initially to avoid the // reallocation, but it doesn't do it yet (as of Go1.20rc1). functions := append([]FunctionObject{ someFunction, someFunction2, ... }, opts...) // Does not allocate -- the slice is simply passed to the next function. func2(functions...) } // Minimise allocations (1 allocation). func func2(opts ...FunctionObject) { // Pre-allocate the required space to avoid any further append // allocations within this function. functions := make([]FunctionObject, 0, 2 + len(opts)) functions = append(functions, someFunction3) functions = append(functions, someFunction4) functions = append(functions, opts...) func3(functions...) }
Anda boleh pergi selangkah lebih jauh dan menggunakan semula kapasiti ganti dalam opts
tanpa memperuntukkan kepingan yang mengandungi item yang akan ditambah (0-1 peruntukan setiap fungsi). Walau bagaimanapun, ini rumit dan terdedah kepada ralat - saya tidak mengesyorkannya.
Atas ialah kandungan terperinci Pergi |. Cara yang cekap dan boleh dibaca untuk menambahkan kepingan dan menghantar ke fungsi variadic. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!