<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
golang這個語言用起來和java、 c#之類語言差不多,和c/c++差別比較大,有自動管理記憶體機制,省心省力。
然而,如果寫golang真的按寫java的習慣去寫,也容易出問題,因為golang中有指標的概念,雖然這個指標是c/c++的自動化版本,但是卻也有指標的特徵,如果不熟悉其中原理,寫出來的程式雖然不至於有執行BUG,效能卻不友好。
因此,不能完全以寫java的思路去寫golang,一定要注意其中差別。
我們知道,在java之中,除了基本型別之外,所有的變數型別都是參照型別,你可以隨意的將參照當作引數傳遞,也可以將參照當作返回值返回,都不會有任何問題。
public class Main { static class Person{ private String name; private String addr; private int age; public void addAge() { age ++; } } private static Person addAge(Person person) { person.addAge(); return person;//可以這麼返回,沒任何問題 } public static void main(String[] args){ Person person = new Person(); addAge(person);//可以這麼呼叫,沒任何問題 } }
如果你沒寫過c/c++,會覺得這一切顯得這麼自然,彷彿這是最常規的操作。然而如果你寫過c/c++,就會發現這麼寫並不是常態,而是非常美好的事情,在c/c++裡面必須避免這麼寫。
class Person { private: string name; string addr; int age; public: void addAge() { this->age++; } }; Person addAge(Person person) { person.addAge(); return person; //不能直接返回,會拷貝person物件 } int main() { Person person; addAge(person);//不能直接傳遞,會拷貝person物件 }
如上面程式碼所示,如果將person物件直接傳遞或者返回,會拷貝物件中的資料,產生額外的開銷,因為這是按值傳遞的模式。在java中也有這種按值傳遞的拷貝,但是隻會在基本型別上起作用,而基本型別體積很小,long才8個位元組,int 4個位元組,物件都是按參照傳遞。
在c++中解決這個問題不止一種手段,但是寫出來的程式碼都非常蹩腳難看。在這裡我們用指標來解決這個拷貝問題
class Person { private: string name; string addr; int age; public: void addAge() { this->age++; } }; Person* addAge(Person* person) { person->addAge(); return person; //可以返回,不會拷貝整個物件,只會拷貝指標(8位元組) } int main() { Person person; addAge(&person);//取地址後傳遞, 不會拷貝整個物件,只會拷貝指標(8個位元組) //或者 Person* pPerson = new Person; addAge(pPerson);//直接傳遞指標 delete pPerson;//動態分配必須刪除,否則有記憶體洩露風險 }
c++的做法是不是比java費事的多,所以平時我們吐槽java語法臃腫被c#、person、kotlin呼叫,而它卻能吊打c++,因為c++能讓你好好的傳遞引數和返回值都做不到。
golang整體的機制雖然偏向於java的易用性,而在變數傳遞返回這一塊,卻繼承了c++的習慣,區分按值傳遞和按指標傳遞,如果寫程式碼的時候值和指標不分,雖然程式不會報錯,但是卻會產生額外的拷貝開銷,對效能不友好。
type Person struct { name string addr string age int } func (this* Person) addAge() { this.age++ } func addAge(person Person) Person { person.addAge() return person //不能直接返回,會拷貝person物件 } func main() { person := Person{} addAge(person)//不能直接傳遞,會拷貝person物件 }
上面的程式碼就是個錯誤示範,在java中這麼寫完全沒問題,在golang中卻不行,因為這是按值傳遞,會拷貝物件,就跟c/c++一樣。
type Person struct { name string addr string age int } func (this* Person) addAge() { this.age++ } func addAge(person* Person) *Person { person.addAge() return person //可以返回,不會拷貝整個物件,只會拷貝指標(8位元組) } func main() { person := Person{} addAge(&person)//取地址後傳遞, 不會拷貝整個物件,只會拷貝指標(8個位元組) //或 person1 := new(Person) addAge(person1)//直接傳遞指標, 不會拷貝整個物件,只會拷貝指標(8個位元組) }
這是這是正確的使用方式,按指標傳遞,就跟c/c++一樣。
於此同時,當你直接使用golang內建的map或者切片型別,不用擔心這個問題,因為make出來的map或者切片,預設就是指標型別,傳遞和返回時不會按值拷貝。
func doSome(input map[string]string) map[string]string { input["hello"] = "world" return input //可以直接返回,不會按值拷貝,map預設是一個指標 } func main() { data := make(map[string]string,5) doSome(data) //可直接傳遞,不會按值拷貝,map是一個指標 }
所以,如果你從java轉到golang,同時又沒有寫過c/c++,那麼要萬分注意這個問題,千萬不能完全以寫java程式碼的習慣去寫go,否則在迴圈中出現大物件只拷貝,會是效能毒藥。
總而言之,golang這門計算機語言,同時具有java和c/c++的特徵,要能好好使用,需要有這兩門語言的基礎。
總結
到此這篇關於go語言中值型別和指標型別的文章就介紹到這了,更多相關go語言值型別和指標型別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45