[{"data":1,"prerenderedAt":496},["ShallowReactive",2],{"\u002Fblogs\u002Fa-definitive-guide-to-pointers-in-go":3},{"id":4,"title":5,"body":6,"coverImage":481,"description":484,"extension":485,"meta":486,"navigation":108,"path":488,"publishedOn":489,"seo":490,"sitemap":491,"stem":494,"__hash__":495},"content\u002Fblogs\u002Fa-definitive-guide-to-pointers-in-go.md","Understanding Pointers in Go: A Practical Guide",{"type":7,"value":8,"toc":475},"minimark",[9,13,16,21,32,38,41,49,52,55,59,70,81,178,195,201,266,281,287,365,386,395,399,402,405,408,423,426,430,433,436,459,462,465,468,471],[10,11,12],"p",{},"If you are finding it difficult to grasp the concept of pointers in Go, you are\nnot alone. Having worked primarily with interpreted languages like Python which\ndo not expose pointers as part of the language model, I can relate. However,\nbecause Go is a systems oriented language, understanding pointers is essential\nfor writing performant, memory efficient and predictable software. As a Go\ndeveloper, this is not a topic you can safely gloss over.",[10,14,15],{},"In this article, I will clarify what pointers are in Go and how to use them\ncorrectly.",[17,18,20],"h2",{"id":19},"pointers-are-a-type-of-variable","Pointers Are a Type of Variable",[10,22,23,24,31],{},"The official Go tutorial, \"A Tour of Go\" defines pointers as follows\n(",[25,26,30],"a",{"href":27,"rel":28},"https:\u002F\u002Fgo.dev\u002Ftour\u002Fmoretypes\u002F1",[29],"nofollow","source","):",[33,34,35],"blockquote",{},[10,36,37],{},"\"Go has pointers. A pointer holds the memory address of a value\".",[10,39,40],{},"This definition is concise and accurate. A pointer is a variable whose value is\na memory address.",[10,42,43,44,48],{},"To restate this more explicitly: a pointer does not store the value itself; it\nstores the address in memory where that value resides (for example, something\nlike ",[45,46,47],"code",{},"0x7ffee4b8c9a0",").",[10,50,51],{},"The size of a pointer depends of the system architecture, so on a 32-bit system,\na pointer is 4 bytes and on a 64-bit system, a pointer is a 8 bytes in size.",[10,53,54],{},"Since pointers are small (just an address), they allow us to pass and manipulate\nlarge data structures efficiently without copying the entire value. Instead of\nduplicating data, we can operate on the original value via its address.",[17,56,58],{"id":57},"declaring-and-using-pointers","Declaring and Using Pointers",[10,60,61,62,65,66,69],{},"Go provides two primary operators for working with pointers - the ",[45,63,64],{},"*"," (asterisk)\nand the ",[45,67,68],{},"&"," (ampersand), each serving a different purpose depending on the\ncontext.",[10,71,72,73,76,77,80],{},"To declare a pointer type, we use the form ",[45,74,75],{},"*T"," represents \"pointer to a value\nof type ",[45,78,79],{},"T","\" as described in the example code snippet below:",[82,83,88],"pre",{"className":84,"code":85,"language":86,"meta":87,"style":87},"language-go shiki shiki-themes everforest-dark","package main\n\nimport \"fmt\"\n\nfunc main() {\n    var p *int\n    fmt.Println(p) \u002F\u002F should print \u003Cnil>\n}\n","go","",[45,89,90,103,110,121,126,141,156,172],{"__ignoreMap":87},[91,92,95,99],"span",{"class":93,"line":94},"line",1,[91,96,98],{"class":97},"s9lfW","package",[91,100,102],{"class":101},"sP-ue"," main\n",[91,104,106],{"class":93,"line":105},2,[91,107,109],{"emptyLinePlaceholder":108},true,"\n",[91,111,113,117],{"class":93,"line":112},3,[91,114,116],{"class":115},"sFWo_","import",[91,118,120],{"class":119},"sySyC"," \"fmt\"\n",[91,122,124],{"class":93,"line":123},4,[91,125,109],{"emptyLinePlaceholder":108},[91,127,129,133,137],{"class":93,"line":128},5,[91,130,132],{"class":131},"safYi","func",[91,134,136],{"class":135},"sRC7j"," main",[91,138,140],{"class":139},"sY0Nt","() {\n",[91,142,144,148,151,153],{"class":93,"line":143},6,[91,145,147],{"class":146},"sDOmQ","    var",[91,149,150],{"class":139}," p ",[91,152,64],{"class":146},[91,154,155],{"class":101},"int\n",[91,157,159,162,165,168],{"class":93,"line":158},7,[91,160,161],{"class":139},"    fmt.",[91,163,164],{"class":135},"Println",[91,166,167],{"class":139},"(p) ",[91,169,171],{"class":170},"s67c6","\u002F\u002F should print \u003Cnil>\n",[91,173,175],{"class":93,"line":174},8,[91,176,177],{"class":139},"}\n",[10,179,180,181,183,184,187,188,191,192,194],{},"In the code above, ",[45,182,10],{}," is declared as a pointer to an ",[45,185,186],{},"int"," and its default\nvalue is ",[45,189,190],{},"nil"," since in Go, an uninitialised pointer is always ",[45,193,190],{},".",[10,196,197,198,200],{},"The ",[45,199,68],{}," operator returns the memory address of a variable as shown in the\nexample below:",[82,202,204],{"className":84,"code":203,"language":86,"meta":87,"style":87},"package main\n\nimport \"fmt\"\n\nfunc main() {\n    msg := \"Hello World!\"\n    fmt.Println(&msg) \u002F\u002F prints a memory address (e.g., 0x239a5e620070)\n}\n",[45,205,206,212,216,222,226,234,245,262],{"__ignoreMap":87},[91,207,208,210],{"class":93,"line":94},[91,209,98],{"class":97},[91,211,102],{"class":101},[91,213,214],{"class":93,"line":105},[91,215,109],{"emptyLinePlaceholder":108},[91,217,218,220],{"class":93,"line":112},[91,219,116],{"class":115},[91,221,120],{"class":119},[91,223,224],{"class":93,"line":123},[91,225,109],{"emptyLinePlaceholder":108},[91,227,228,230,232],{"class":93,"line":128},[91,229,132],{"class":131},[91,231,136],{"class":135},[91,233,140],{"class":139},[91,235,236,239,242],{"class":93,"line":143},[91,237,238],{"class":139},"    msg ",[91,240,241],{"class":146},":=",[91,243,244],{"class":119}," \"Hello World!\"\n",[91,246,247,249,251,254,256,259],{"class":93,"line":158},[91,248,161],{"class":139},[91,250,164],{"class":135},[91,252,253],{"class":139},"(",[91,255,68],{"class":146},[91,257,258],{"class":139},"msg) ",[91,260,261],{"class":170},"\u002F\u002F prints a memory address (e.g., 0x239a5e620070)\n",[91,263,264],{"class":93,"line":174},[91,265,177],{"class":139},[10,267,268,269,272,273,276,277,280],{},"In the code snippet above, the ",[45,270,271],{},"msg"," variable stores the string ",[45,274,275],{},"\"Hello World!\"","\nand ",[45,278,279],{},"&msg"," returns the address in memory where that string value is stored. The\nexact address will vary each time the program is run.",[10,282,283,284,286],{},"When used with a pointer value, the ",[45,285,64],{}," operator dereferences the pointer.\nDereferencing means accessing the value stored at the memory address the pointer\nholds.",[82,288,290],{"className":84,"code":289,"language":86,"meta":87,"style":87},"package main\n\nimport \"fmt\"\n\nfunc main() {\n    msg := \"Hello World!\"\n    ptr := &msg       \u002F\u002F ptr stores the address of msg\n    fmt.Println(*ptr) \u002F\u002F prints \"Hello World!\"\n}\n",[45,291,292,298,302,308,312,320,328,344,360],{"__ignoreMap":87},[91,293,294,296],{"class":93,"line":94},[91,295,98],{"class":97},[91,297,102],{"class":101},[91,299,300],{"class":93,"line":105},[91,301,109],{"emptyLinePlaceholder":108},[91,303,304,306],{"class":93,"line":112},[91,305,116],{"class":115},[91,307,120],{"class":119},[91,309,310],{"class":93,"line":123},[91,311,109],{"emptyLinePlaceholder":108},[91,313,314,316,318],{"class":93,"line":128},[91,315,132],{"class":131},[91,317,136],{"class":135},[91,319,140],{"class":139},[91,321,322,324,326],{"class":93,"line":143},[91,323,238],{"class":139},[91,325,241],{"class":146},[91,327,244],{"class":119},[91,329,330,333,335,338,341],{"class":93,"line":158},[91,331,332],{"class":139},"    ptr ",[91,334,241],{"class":146},[91,336,337],{"class":146}," &",[91,339,340],{"class":139},"msg       ",[91,342,343],{"class":170},"\u002F\u002F ptr stores the address of msg\n",[91,345,346,348,350,352,354,357],{"class":93,"line":174},[91,347,161],{"class":139},[91,349,164],{"class":135},[91,351,253],{"class":139},[91,353,64],{"class":146},[91,355,356],{"class":139},"ptr) ",[91,358,359],{"class":170},"\u002F\u002F prints \"Hello World!\"\n",[91,361,363],{"class":93,"line":362},9,[91,364,177],{"class":139},[10,366,367,368,370,371,374,375,378,379,381,382,385],{},"In the example above, ",[45,369,271],{}," is initialised with a string value of\n",[45,372,373],{},"Hello World!",". Thereafter, the ",[45,376,377],{},"ptr"," variable stores the address of ",[45,380,271],{}," and\nthen ",[45,383,384],{},"*ptr"," accesses (dereferences) the value at that address.",[10,387,388,389,391,392,394],{},"Note the differences between ",[45,390,377],{}," and ",[45,393,384],{}," where one holds the address and\nthe other holds the value at that address.",[17,396,398],{"id":397},"why-pointers-matter-in-go","Why Pointers Matter in Go",[10,400,401],{},"As you can see, pointers play a significant role in Go. They allow developers to\nwrite performant software in ways that may not be as straightforward in\nlanguages like Python. So, what are some real-world use cases of pointers?",[10,403,404],{},"For starters, pointers allow us to load large amounts of data (think a few MBs\nor more) and manipulate them without copying them across various sections of the\nprogram. Failing to do so may lead to increased memory usage, since the large\ndata may not only be loaded into memory but also duplicated multiple times\nduring processing.",[10,406,407],{},"Go was built from the ground up to handle concurrent applications (e.g., web\nservers). Sharing the state of data and safely modifying it without corruption\nor race conditions is of utmost importance in such environments. Go pointers,\ncombined with mutex locks, allow us to do exactly that with ease. As a side\nnote, I will discuss writing concurrent programs in Go in a future article.",[10,409,410,411,413,414,416,417,422],{},"As discussed earlier, pointers in Go are initialized to ",[45,412,190],{},", and we can always\ncheck for the ",[45,415,190],{}," value before processing data. This particular safety\nmechanism is often missing or handled differently in other languages and can\npotentially lead to disastrous situations. If you are interested in learning\nmore about the broader context, check out the presentation\n\"",[25,418,421],{"href":419,"rel":420},"https:\u002F\u002Fwww.infoq.com\u002Fpresentations\u002FNull-References-The-Billion-Dollar-Mistake-Tony-Hoare",[29],"Null References: The Billion Dollar Mistake","\"\nby Tony Hoare, who introduced the idea of null references.",[10,424,425],{},"Go also does not support pointer arithmetic (unlike C), which makes pointer\nusage safer and more predictable. You can hold an address and dereference it,\nbut it is not possible to manually offset it.",[17,427,429],{"id":428},"final-thoughts","Final Thoughts",[10,431,432],{},"Pointers in Go are not inherently complex, as they are conceptually just\nvariables that store memory addresses. The difficulty lies in understanding when\nand why to use them, not in their syntax.",[10,434,435],{},"Remember these three rules:",[437,438,439,447,453],"ol",{},[440,441,442,444,445,194],"li",{},[45,443,75],{}," defines a pointer to type ",[45,446,79],{},[440,448,449,452],{},[45,450,451],{},"&value"," provides the address of a value.",[440,454,455,458],{},[45,456,457],{},"*pointer"," retrieves the value stored at an address.",[10,460,461],{},"Once this mental model is internalized, pointers will feel like a natural\nextension of Go's type system rather than an intimidating concept.",[10,463,464],{},"Pointers are a powerful feature of the language, but improper usage can lead to\nbuggy and unexpected behavior. Unless specifically required, refrain from\nmutating data through pointers.",[10,466,467],{},"Most of the time, Go code is sufficiently fast, and its Garbage Collector (GC)\nwill clean up unused allocations. Using pointers solely to squeeze out marginal\nperformance gains often provides little benefit.",[10,469,470],{},"Instead, perform proper benchmarking and profiling to identify performance\nbottlenecks before refactoring. Pointers should be used primarily when mutation\nof shared state is required, while immutability and passing by value should\ngenerally be preferred.",[472,473,474],"style",{},"html pre.shiki code .s9lfW, html code.shiki .s9lfW{--shiki-default:#D699B6}html pre.shiki code .sP-ue, html code.shiki .sP-ue{--shiki-default:#7FBBB3}html pre.shiki code .sFWo_, html code.shiki .sFWo_{--shiki-default:#83C092}html pre.shiki code .sySyC, html code.shiki .sySyC{--shiki-default:#DBBC7F}html pre.shiki code .safYi, html code.shiki .safYi{--shiki-default:#E67E80}html pre.shiki code .sRC7j, html code.shiki .sRC7j{--shiki-default:#A7C080}html pre.shiki code .sY0Nt, html code.shiki .sY0Nt{--shiki-default:#D3C6AA}html pre.shiki code .sDOmQ, html code.shiki .sDOmQ{--shiki-default:#E69875}html pre.shiki code .s67c6, html code.shiki .s67c6{--shiki-default:#859289;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":87,"searchDepth":105,"depth":105,"links":476},[477,478,479,480],{"id":19,"depth":105,"text":20},{"id":57,"depth":105,"text":58},{"id":397,"depth":105,"text":398},{"id":428,"depth":105,"text":429},{"url":482,"alt":483},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fa-definitive-guide-to-pointers-in-go.png","A Definitive Guide to Pointers in Go","Learn how pointers work in Go with clear explanations and practical examples. This guide covers pointer types, memory addresses, dereferencing and why pointers matter for writing efficient and reliable Go programs.","md",{"status":487},"published","\u002Fblogs\u002Fa-definitive-guide-to-pointers-in-go","2026-02-25",{"title":5,"description":484},{"loc":492,"lastmod":489,"changefreq":493,"priority":94},"\u002Fa-definitive-guide-to-pointers-in-go","yearly","blogs\u002Fa-definitive-guide-to-pointers-in-go","uqPU3rzdOi9_k7OGXyS_nqiaL7TtAvDk93QclWfokmM",1788263772972]