#### golang的append到底干了啥 ####

?代碼1.0

package mainimport "fmt"func main() {a := make([]int64, 0, 0) // 改為 a := make([]int64, 0, 2) 時執行輸出也都一樣的println(fmt.Sprintf("a: %v", a))// 輸出:a: []solve(a)println(fmt.Sprintf("a: %v", a))// 輸出:a: []
}func solve(currA []int64) {currA = append(currA, 1)println(fmt.Sprintf("currA: %v", currA))// 輸出:currA: [1]
}

在調solve函數時,發生了引用的復制:currA = a,引用指的是這個東西:

// runtime/slice.gotype slice struct {array unsafe.Pointer // 數組指針len int // 長度 注意:append時len是占位的cap int // 容量
}

也就是產生了slice struct的兩個實例——currA和a,其中currA中各項(包含:array指針、len、cap三個字段)的值是從a的各項值復制來的,其中array指針相同則意味著currA和a指向的底層數組是一個,但是后續currA和a會各自維護自己的len和cap。

這也就是為什么【在子函數solve里append后不會影響父函數main里的切片,但是在子函數solve里用下標修改元素值后是會影響父函數main里的切片(下標修改的過程見下面代碼)】的原因。

package mainimport "fmt"func main() {a := make([]int64, 0, 0)a = append(a, 1)println(fmt.Sprintf("a: %v", a))// 輸出:a: []solve(a)println(fmt.Sprintf("a: %v", a))// 輸出:a: [2]
}func solve(currA []int64) {currA[0] = 2println(fmt.Sprintf("currA: %v", currA))// 輸出:currA: [2]
}

?代碼2.0

package mainimport "fmt"func main() {a := make([]int64, 0, 2) // 后續不需要擴容println(fmt.Sprintf("a: %v", a))// 輸出:a: []b := append(a, 1)println(fmt.Sprintf("a: %v, b: %v", a, b))// 輸出:a: [], b: [1]c := append(a, 2)println(fmt.Sprintf("a: %v, b: %v, c: %v", a, b, c))// 輸出:a: [], b: [2], c: [2]
}

總結分析

append時沒有發生底層數組數據的直接復制;相反,append?函數返回了一個新的切片值,該值可能與原始切片共享相同的底層數組(在不需要擴容的情況下),但具有不同的長度和(可能)容量。

另外,append時會會根據原接片的長度去追加。例如原切片長度為1(下標=0),則append時會在下標為0+1的地方追加。

詳細分析

當你執行?b := append(a, 1)?時,這里發生了幾件事情:

  1. 如果?append?操作不需要擴展底層數組(即新元素的添加不會導致切片的容量不足),那么?append?會直接在底層數組的末尾添加新元素,并返回一個新的切片值。這個新的切片值會包含原始切片的所有元素(在這個例子中是空的,因為沒有元素),加上新追加的元素。重要的是,這個新的切片值會共享原始切片的底層數組(如果可能的話),但它會有自己的長度(現在至少為 1,因為我們添加了一個元素)。

  2. 在這個特定的例子中,由于?a?是空的,且其容量足以容納至少一個額外的元素(因為我們設置了容量為 2),append(a, 1)?實際上是在?a?的底層數組的末尾(盡管這個數組目前還是空的)添加了一個元素,并返回了一個新的切片值?b。這個新的切片值?b?指向與?a?相同的底層數組(在這個例子中這個“相同”的底層數組實際上還沒有被使用來存儲任何元素,但它已經為存儲元素做好了準備),但它的長度是 1,因為它現在包含一個元素。

  3. 然而,重要的是要理解?a?和?b?是兩個不同的切片值。盡管它們可能(在這個例子中確實)共享相同的底層數組,但每個切片值都有自己獨立的長度和容量。當你將?b?賦值給一個新變量時,你并沒有復制底層數組,而是創建了一個新的切片頭(包含指向底層數組的指針、長度和容量),并將其賦值給該變量。

  4. 因此,當你說“包含了 a 的所有元素”時,你實際上是在說新切片?b?包含了原始切片?a?在追加操作之前所擁有的所有元素(在這個例子中是空的),并且額外添加了一個新的元素。這并不意味著底層數組的數據被復制了;相反,它意味著新的切片值?b?指向了與?a?相同的底層數組(或一個新的、更大的數組,如果追加操作導致了切片的重新分配),但具有不同的長度。

代碼2.1

package mainimport "fmt"func main() {a := make([]int64, 0, 0) // 后續不需要擴容println(fmt.Sprintf("a: %v", a))// 輸出:a: []b := append(a, 1)println(fmt.Sprintf("a: %v, b: %v", a, b))// 輸出:a: [], b: [1]c := append(a, 2)println(fmt.Sprintf("a: %v, b: %v, c: %v", a, b, c))// 輸出:a: [], b: [1], c: [2]
}

如果append時需要擴容,則將原數組的值復制到擴容后的數組。執行到【b := append(a, 1)】和【c := append(a, 2)】時會發生擴容,但擴容不會對a產生任何影響,因為沒有【a?:= append(a, 1或2)】的操作。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/39022.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/39022.shtml
英文地址,請注明出處:http://en.pswp.cn/web/39022.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

企業出海如何應對國際差旅報銷的復雜性?

在全球化浪潮的推動下,越來越多的中國企業開始邁向國際市場。然而,企業在“走出去”的過程中不僅面臨新的商機,也需要克服諸多挑戰。尤其是國際差旅報銷的復雜性,成為出海企業必須解決的重要問題。 國際差旅報銷的四大挑戰 多元…

【分布式數據倉庫Hive】常見問題及解決辦法

目錄 一、啟動hive時發現log4j版本和hadoop的版本有沖突 解決辦法:刪除hive下高版本的slf4j 二、啟動hive報錯 Exception in thread "main" java.lang.NoSuchMethodError:com.google.common.base.Preconditions.checkArgument(ZLjava/lang/Object;)V …

postgres數據庫的流復制

1. 流復制和邏輯復制的差異 邏輯復制和流復制最直觀的不同是,邏輯復制支持表級別復制區分點事原理不同 邏輯日志是在wal日志產生的數據庫上,由邏輯解析模塊對wal日志進行初步的解析,解析結果是ReorderBufferChange(理解為HeapTup…

干貨分享|如何將前端代理服務器(BFF)接入身份認證(3完結篇)

續集3 前篇文章在前面發布,同學們可以自行找一下。 本篇文章將繼續通過實例來詳細講解如何將前端代理服務器(BFF)接入身份認證。我們將使用一個示例應用來演示 BFF 與身份認證的集成過程。 3 在 Full BFF 中接入認證平臺 本小節將介紹如何…

Raylib 坐標系適應與GPU繪制參數

通過750 - 鼠標坐標&#xff0c;把原點在左上角的鼠標坐標變成左下角 實現輸入數據后的坐標系同GPU原點在左下角坐標相同&#xff0c; 比數組0&#xff0c;0對應左上角好&#xff0c; 此時實際上數組0&#xff0c;0對應左下角 #include <raylib.h> // 感受&#xff1a…

【SpringBoot配置文件讀取】無法讀取yaml文件中文字符

1. yaml配置文件 注意要將該文件編碼格式改為UTF-8 spring:application:name: 好好學習admin:name: 李斯age: 24books:- name: 數據結構desc: 數據書- name: 編譯原理desc: 編譯書2.配置實體類 Data設置get&#xff0c;set方法Component注冊為BeanConfigurationProperties(p…

開發者聊科學作息時間表

非常有幸對科學作息時間表app的開發者做一次采訪。 問&#xff1a;你對科學作息時間表app滿意么&#xff1f; 答&#xff1a;非常不滿意&#xff0c;我們的設想是讓他更智能&#xff0c;更多的提醒方式&#xff0c;更好的交互體驗。如果作為一個鬧鐘他是非常不合格的&#xff0…

輕松駕馭Python 3.11:Windows環境下的安裝與配置全攻略

引言 Python是一種功能強大且易于學習的編程語言&#xff0c;廣泛應用于Web開發、數據分析、人工智能和自動化等領域。為了在Windows中使用Python&#xff0c;首先需要安裝Python解釋器并進行環境配置。本文將詳細介紹如何在Windows中安裝Python 3.11并進行環境配置。 目錄 …

R可視化數據必要格式——長格式

一、引言 我們在對數據進行可視化時遇到最頭疼、最常見的問題是什么&#xff1f;數據問題。 因為我們往往不會從零自己編程進行可視化&#xff0c;往往是現有模板或積累&#xff0c;而正確的數據格式對應正確的圖形包要求&#xff0c;一定會正確出圖&#xff0c;所以只有一個問…

調試 hipcc 的llvm llc gpu目標代碼生成模塊

源碼&#xff1a; hello_vectorAdd.hip: __global__ void vectorAdd(const float *A, const float *B, float *C) {int i blockDim.x * blockIdx.x threadIdx.x;C[i] A[i] B[i] 0.0f; } Makefile: x.O1.s: hello_vectorAdd.hip../../local_amdgpu/bin/clang ./hello_vec…

力扣hot100-普通數組2

文章目錄 題目&#xff1a;輪轉數組方法1-使用額外的數組方法2-三次反轉數組 除自身以外數組的乘積方法1-用到了除法方法2-前后綴乘積法 題目&#xff1a;輪轉數組 原題鏈接&#xff1a;輪轉數組 方法1-使用額外的數組 方法1是自己寫出來的。方法2參考的別人的&#xff0c;…

通配符和正則表達式之間的關系

通配符和正則表達式&#xff08;正則&#xff09;都是用于匹配字符串的工具&#xff0c;但它們的復雜性和用途有所不同。下面是它們之間的主要關系和區別&#xff1a; 通配符 通配符主要用于簡單的模式匹配&#xff0c;常見于文件系統操作中&#xff0c;例如在命令行中查找文…

AttackGen:一款基于LLM的網絡安全事件響應測試工具

關于AttackGen AttackGen是一款功能強大的網絡安全事件響應測試工具&#xff0c;該工具利用了大語言模型和MITRE ATT&CK框架的強大功能&#xff0c;并且能夠根據研究人員選擇的威脅行為組織以及自己組織的詳細信息生成定制化的事件響應場景。 功能介紹 1、根據所選的威脅行…

【MindSpore學習打卡】應用實踐-計算機視覺-FCN圖像語義分割-基于MindSpore實現FCN-8s進行圖像語義分割的教程

圖像語義分割是計算機視覺領域中的一個重要任務&#xff0c;它旨在對圖像中的每個像素進行分類&#xff0c;從而實現對圖像內容的詳細理解。在眾多圖像語義分割算法中&#xff0c;全卷積網絡&#xff08;Fully Convolutional Networks, FCN&#xff09;因其端到端的訓練方式和高…

7.7、指針和函數

代碼 #include <iostream> using namespace std;//實現兩個數字進行交換 void swap01(int a, int b) {int temp a;a b;b temp;cout << "swap01a " << a << endl;cout << "swap01b " << b << endl; }void sw…

08 docker Registry搭建docker私倉

目錄 本地鏡像發布流程 1. docker pull registry 下載鏡像 2. docker run 運行私有庫registry 3. docker commit 構建鏡像 4. docker tag 修改新鏡像&#xff0c;使之符合私服規范tag 5. 修改配置文件使之支持http 6. curl驗證私服庫上有什么鏡像 7. push推送 pull拉取 …

Activity、Window、DecorView的關系

目錄 一、Activity、Window、DecorView的層級關系如下圖所示&#xff1a; 1、Activity 2、Window 3、DecorView 二、DecorView初始化相關源碼 三、DecorView顯示時機 前言&#xff1a; 不同的Android版本有差異&#xff0c;以下基于Android 11進行講解。 一、Activi…

Halide AOT模式

這種模式會提前&#xff0c;會提前編譯好&#xff0c;變成dll什么的&#xff0c;可接受任何輸入的參數運行。 然后這樣調用&#xff0c;必須要make一下前一個file&#xff0c;才有后面的.h

魔行觀察-AI數據分析-蜜雪冰城

摘要 本報告旨在評估蜜雪冰城品牌作為投資對象的潛力和價值&#xff0c;基于其經營模式、門店分布、人均消費、覆蓋省份等關鍵指標進行分析。 數據數據源&#xff1a;魔行觀察&#xff1a;http://www.wmomo.com/#/brand/brandDetails?code10013603 品牌概覽 蜜雪冰城是中國…

拼多多職位數據信息采集

數據信息采集 洛哥爬蟲【視頻】 愛寫爬蟲 我愛扣腳 https://careers.pinduoduo.com/jobs#/from DrissionPage import ChromiumPage, ChromiumOptions def fetch_pinduoduo_jobs():# 創建ChromiumOptions對象co ChromiumOptions()# 提供瀏覽器可執行文件的路徑path rC:\Pro…