[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"sanity-4tcPe_NjnRcPnBTYqeJtODcPDDX9zmaUD8VbbsDigAM":3,"sanity-UGMsPUkDu3TISOdWfhv1rit-V4LC0AJbR1132nXhJho":940},{"data":4,"sourceMap":-1},{"latestPodcast":5,"latestReleases":14,"post":39,"recent":915},[6],{"_id":7,"publishedAt":8,"slug":9,"sponsored":12,"title":13},"d53f9358-3bb2-4f69-aebe-d31d19522cd4","2026-07-10T07:40:00.000Z",{"_type":10,"current":11},"slug","building-more-than-just-an-agent-harness",null,"Building more than just an agent harness",[15,21,27,33],{"_id":16,"publishedAt":17,"slug":18,"title":20},"eb5b66eb-9410-4329-83bb-22bbff39402a","2026-04-28T13:00:00.000Z",{"_type":10,"current":19},"turn-scattered-knowledge-into-trusted-intelligence","Turning scattered knowledge into trusted intelligence: Stack Internal 2026.3",{"_id":22,"publishedAt":23,"slug":24,"title":26},"369c2401-b62e-4a37-8ff8-bf603023ecad","2026-03-02T15:03:00.988Z",{"_type":10,"current":25},"what-s-new-at-stack-overflow-march-2026","What’s new at Stack Overflow: March 2026",{"_id":28,"publishedAt":29,"slug":30,"title":32},"5e9053a4-07ea-447c-91ea-29e0b6228537","2026-02-02T15:00:00.000Z",{"_type":10,"current":31},"what-s-new-at-stack-overflow-february-2026","What’s new at Stack Overflow: February 2026",{"_id":34,"publishedAt":35,"slug":36,"title":38},"a1b538eb-a8a6-46d0-80a1-ac70ec9bb935","2026-01-05T10:00:00.000-05:00",{"_type":10,"current":37},"what-s-new-at-stack-overflow-january-2026","What’s new at Stack Overflow: January 2026",{"_createdAt":40,"_id":41,"_rev":42,"_system":43,"_type":46,"_updatedAt":47,"author":48,"body":65,"comments":870,"dateUrl":871,"excerpt":872,"image":873,"legacyBody":876,"product":12,"publishedAt":879,"slug":880,"sponsored":12,"tags":882,"title":914,"visible":870},"2023-05-24T12:50:59Z","wp-post-19894","7ouUQ4nvxziL2qtJFh7enh",{"base":44},{"id":41,"rev":45},"LIB4H7UiOBRX1pcyrgjaJe","blogPost","2026-07-06T15:18:46Z",[49],{"_createdAt":50,"_id":51,"_rev":52,"_type":53,"_updatedAt":54,"avatar":55,"bio":60,"employee":61,"name":62,"slug":63},"2023-05-23T16:27:18Z","wp-author-cap-19604","dgl3SCUzppW3U2LvCoP6c0","blogAuthor","2023-06-20T15:05:12Z",{"_type":56,"asset":57},"image",{"_ref":58,"_type":59},"image-f8e14edd7735b5ad724714848110bf7e35d71d9c-1329x1688-jpg","reference","As Chief Engineer, he architected and built the first iteration of Mender. He is also a hands-on Go developer of OTA updater for embedded Linux devices, working with various embedded devices (mostly ARM-based).","none","Marcin Pasinski",{"current":64},"marcin-pasinski",[66,89,108,116,125,133,143,151,159,167,175,183,191,199,207,224,232,240,248,256,264,272,281,322,337,345,348,351,359,362,365,373,376,379,387,403,411,419,469,485,592,600,630,638,646,654,662,685,693,747,755,763,771,779,787,815,823,842],{"_key":67,"_type":68,"children":69,"markDefs":84,"style":88},"d2e4dd302b8a","block",[70,75,80],{"_key":71,"_type":72,"marks":73,"text":74},"d2e4dd302b8a0","span",[],"Impossibly tight deadlines, unrealistic schedules, and constant pressure to develop and release applications on time, while at the same time achieving excellent quality. Sound familiar? Faster time-to-market for embedded applications is indeed a critical consideration for embedded development teams. But how do you develop an approach for delivering applications faster while maintaining quality and security as a priority? In this context, the product engineering team behind the OTA software update manager ",{"_key":76,"_type":72,"marks":77,"text":79},"d2e4dd302b8a1",[78],"f2141b573ff8","Mender.io",{"_key":81,"_type":72,"marks":82,"text":83},"d2e4dd302b8a2",[],", went through the process of selecting the best programming language for developing both the embedded client and server parts of Mender. In this evaluation process Go, C, and C++ were shortlisted as candidates. Some of the lessons learned from this evaluation process are explained and why Go was ultimately selected to develop Mender’s client embedded application.",[85],{"_key":78,"_type":86,"href":87,"reference":12},"link","https:\u002F\u002Fmender.io\u002F","normal",{"_key":90,"_type":68,"children":91,"markDefs":105,"style":88},"d6f4b8cd6577",[92,96,101],{"_key":93,"_type":72,"marks":94,"text":95},"d6f4b8cd65770",[],"While this can be quite subjective, ",{"_key":97,"_type":72,"marks":98,"text":100},"d6f4b8cd65771",[99],"a658efe6601f","Go",{"_key":102,"_type":72,"marks":103,"text":104},"d6f4b8cd65772",[]," can be a very productive language for embedded development. This is especially true when it comes to network programming, which is at some point a part of every connected device or application. Go was created by Google to meet the needs of Google developers, and it was mainly developed to try to fix the explosion of complexity within its ecosystem. So efficient compilation, efficient execution, and ease of programming were the three main principles behind developing Go as not all three were available before in the same mainstream language.",[106],{"_key":99,"_type":86,"href":107,"reference":12},"https:\u002F\u002Fstackoverflow.blog\u002F2020\u002F11\u002F02\u002Fgo-golang-learn-fast-programming-languages\u002F",{"_key":109,"_type":68,"children":110,"markDefs":115,"style":88},"604351549df5",[111],{"_key":112,"_type":72,"marks":113,"text":114},"604351549df50",[],"However, we want to stress that Go cannot be considered a replacement for C as there are many places where C is and likely will be needed, such as in the development of real time operating systems or device drivers.",[],{"_key":117,"_type":68,"children":118,"markDefs":123,"style":124},"b91401b110e1",[119],{"_key":120,"_type":72,"marks":121,"text":122},"b91401b110e10",[],"Strict requirements for embedded development",[],"h2",{"_key":126,"_type":68,"children":127,"markDefs":132,"style":88},"5b906dacb850",[128],{"_key":129,"_type":72,"marks":130,"text":131},"5b906dacb8500",[],"After establishing the architecture, the Mender product engineering team evaluated which language would be the best fit to develop the Mender application. The system was supposed to consist of a client running on the embedded device and server acting as a central point where clients were connected to. As such, we had several requirements for the language:",[],{"_key":134,"_type":68,"children":135,"level":140,"listItem":141,"markDefs":142,"style":88},"220461d4cfe0",[136],{"_key":137,"_type":72,"marks":138,"text":139},"220461d4cfe00",[],"As the client application would be running on embedded devices, compiled binaries needed to be as small as possible.",1,"bullet",[],{"_key":144,"_type":68,"children":145,"level":140,"listItem":141,"markDefs":150,"style":88},"bc033fc0167c",[146],{"_key":147,"_type":72,"marks":148,"text":149},"bc033fc0167c0",[],"It needed to work with Yocto, the embedded distribution of Linux.",[],{"_key":152,"_type":68,"children":153,"level":140,"listItem":141,"markDefs":158,"style":88},"a4e766bd4df9",[154],{"_key":155,"_type":72,"marks":156,"text":157},"a4e766bd4df90",[],"The complexity of installation clients should be low, thus limiting external dependencies and libraries.",[],{"_key":160,"_type":68,"children":161,"level":140,"listItem":141,"markDefs":166,"style":88},"9973cb694b94",[162],{"_key":163,"_type":72,"marks":164,"text":165},"9973cb694b940",[],"As it would run on different devices, the language must compile across different architectures.",[],{"_key":168,"_type":68,"children":169,"level":140,"listItem":141,"markDefs":174,"style":88},"2d17af3f17ea",[170],{"_key":171,"_type":72,"marks":172,"text":173},"2d17af3f17ea0",[],"The devices that the Mender client application would run on would be an IoT or networked device, so the language needed access to networking libraries.",[],{"_key":176,"_type":68,"children":177,"markDefs":182,"style":88},"6532f7aed71e",[178],{"_key":179,"_type":72,"marks":180,"text":181},"6532f7aed71e0",[],"The requirements for selecting a new language also covered a few non-functional requirements:",[],{"_key":184,"_type":68,"children":185,"level":140,"listItem":141,"markDefs":190,"style":88},"bb7a5931d53f",[186],{"_key":187,"_type":72,"marks":188,"text":189},"bb7a5931d53f0",[],"As many programmers as possible within our organization needed to be able to understand the language.",[],{"_key":192,"_type":68,"children":193,"level":140,"listItem":141,"markDefs":198,"style":88},"d0f3c45e3ee0",[194],{"_key":195,"_type":72,"marks":196,"text":197},"d0f3c45e3ee00",[],"It had to be as easy as possible to share and reuse the existing code between existing applications written in C and reuse code between the client and server applications.",[],{"_key":200,"_type":68,"children":201,"level":140,"listItem":141,"markDefs":206,"style":88},"feaf8f170565",[202],{"_key":203,"_type":72,"marks":204,"text":205},"feaf8f1705650",[],"Development speed was also considered—we have ongoing pressure to add new features quickly.",[],{"_key":208,"_type":68,"children":209,"markDefs":223,"style":88},"08840815460a",[210,214,219],{"_key":211,"_type":72,"marks":212,"text":213},"08840815460a0",[],"A comparison between Go, C, and C++ is outlined in ",{"_key":215,"_type":72,"marks":216,"text":218},"08840815460a1",[217],"strong","Figure 1",{"_key":220,"_type":72,"marks":221,"text":222},"08840815460a2",[],". From the comparison, Go was primarily selected for its support of buffer overflow protection, automatic memory management, use of standard data containers, and its integrated support for JSON, HTTP, and SSL\u002FTLS libraries.",[],{"_key":225,"_type":68,"children":226,"markDefs":231,"style":88},"fd38fcfc7603",[227],{"_key":228,"_type":72,"marks":229,"text":230},"fd38fcfc76030",[],"RequirementCC++GoSize requirements in devicesLowestLow (1.8MB more)Low (2.1 MB more, however will increase with more binaries)Setup requirements in YoctoNoneNoneNoneBuffer under\u002Foverflow protectionNoneLittleYesCode reuse\u002Fsharing from CFEngineGoodEasy (full backwards compatibility)Can import C APIAutomatic memory managementNoAvailable, but not enforcedYesStandard data containersNoYesYesJSONjson-cjsoncppBuilt-inHTTP librarycurlcurlBuilt-inSSL\u002FTLSOpenSSLOpenSSLBuilt-in (TLS is a part of crypto\u002Ftls package)*Figure 1: A table comparison of features across Go, C, and C++",[],{"_key":233,"_type":68,"children":234,"markDefs":239,"style":88},"32d7336d385d",[235],{"_key":236,"_type":72,"marks":237,"text":238},"32d7336d385d0",[],"The evaluation continued to see how Go would stack up against C, C++, and C++\u002FQt for creating a full-blown custom Linux image using Yocto. Pure image size and image size with network stack were compared, as was how the end application would be delivered to a target image. As Go applications can be statically compiled to a single binary, there is no need for any extra virtual environment (like in the case of Java, which requires a virtual machine in addition to binaries) or additional dependencies running on the device to use the Go code.",[],{"_key":241,"_type":68,"children":242,"markDefs":247,"style":88},"a84446408fa2",[243],{"_key":244,"_type":72,"marks":245,"text":246},"a84446408fa20",[],"CC++C++\u002FQtGoSize overhead of the test component, and all the new libraries pulled in, when using the smallest available Yocto image as a basis8.4MB10.2MB20.8MB14.6MBSize with network stack13.4MB (curl)15.2MB (curl)20.8MB*14.6MBShared dependenciesYesYesYesNoExtra Yocto layer neededNoNoYesNoDeployment complexityBinaryBinaryBinary + QtBinaryFigure 2: How Go compares to other programming languages for Yocto builds",[],{"_key":249,"_type":68,"children":250,"markDefs":255,"style":124},"84740df8a9fb",[251],{"_key":252,"_type":72,"marks":253,"text":254},"84740df8a9fb0",[],"Comparing Go vs. C",[],{"_key":257,"_type":68,"children":258,"markDefs":263,"style":88},"8fdf917a2180",[259],{"_key":260,"_type":72,"marks":261,"text":262},"8fdf917a21800",[],"Go was also selected for development due to its extremely rich standard library, which allows for much faster development, especially when compared to C. Go inherits a lot of elements from C, C++, and Python including the expression syntax, control flow statements, data structures, interfaces, pointers, the pass by value concept, parameter parsing syntax, string handling, and garbage collection. With its optimized compiler, Go runs natively on embedded devices.",[],{"_key":265,"_type":68,"children":266,"markDefs":271,"style":88},"d566d5fa2780",[267],{"_key":268,"_type":72,"marks":269,"text":270},"d566d5fa27800",[],"Go did have some disadvantages, which we’ll mention below. They didn’t weigh heavily enough to overcome its advantages, like the development speed and ease of building in the language, but they did factor into our decision. Here’s the other qualities that went into our decision.",[],{"_key":273,"_type":68,"children":274,"markDefs":279,"style":280},"736517087f82",[275],{"_key":276,"_type":72,"marks":277,"text":278},"736517087f820",[],"Size comparison of Go vs. C",[],"h3",{"_key":282,"_type":68,"children":283,"markDefs":321,"style":88},"a7400f05d807",[284,288,293,297,301,305,309,313,317],{"_key":285,"_type":72,"marks":286,"text":287},"a7400f05d8070",[],"Go is bulkier than C when it comes to size, which was one of the few disadvantages it had. If you take “hello world” as the smallest application you can write in Go and use the built-in ",{"_key":289,"_type":72,"marks":290,"text":292},"a7400f05d8071",[291],"code","println",{"_key":294,"_type":72,"marks":295,"text":296},"a7400f05d8072",[]," function, after stripping away debugging symbols it is just over 600 kB in size",{"_key":298,"_type":72,"marks":299,"text":300},"a7400f05d8073",[217]," (snippet 1)",{"_key":302,"_type":72,"marks":303,"text":304},"a7400f05d8074",[],". If you include the ",{"_key":306,"_type":72,"marks":307,"text":308},"a7400f05d8075",[291],"fmt",{"_key":310,"_type":72,"marks":311,"text":312},"a7400f05d8076",[]," package with its dependencies, then the size increases to 1.5 MB ",{"_key":314,"_type":72,"marks":315,"text":316},"a7400f05d8077",[217],"(snippet 2)",{"_key":318,"_type":72,"marks":319,"text":320},"a7400f05d8078",[],".",[],{"_key":323,"_type":68,"children":324,"markDefs":336,"style":88},"44079299efe6",[325,329,333],{"_key":326,"_type":72,"marks":327,"text":328},"44079299efe60",[],"To compare this to C, if you are building a dynamically linked library, then it is a mere 8 kbytes. If you do it static, then the size increases to over 800 kbytes which is surprisingly even larger than the Go binary ",{"_key":330,"_type":72,"marks":331,"text":332},"44079299efe61",[217],"(snippet 3)",{"_key":334,"_type":72,"marks":335,"text":320},"44079299efe62",[],[],{"_key":338,"_type":68,"children":339,"markDefs":344,"style":88},"dd8fb7817b27",[340],{"_key":341,"_type":72,"marks":342,"text":343},"dd8fb7817b270",[],"Snippet 1: smallest Go “hello world” code:",[],{"_key":346,"_type":291,"code":347,"markDefs":12},"3153a8ef27e6","package main\nfunc main() {\n   println(\"hello world\")\n}\n",{"_key":349,"_type":291,"code":350,"markDefs":12},"0b223458903f","$ go build\n     > 938K\n$ go build -ldflags ‘-s -w’\n     > 682K\n$ go build & strip\n     > 623K",{"_key":352,"_type":68,"children":353,"markDefs":358,"style":88},"12d44261d47c",[354],{"_key":355,"_type":72,"marks":356,"text":357},"12d44261d47c0",[],"Snippet 2: Go “standard” “hello world”",[],{"_key":360,"_type":291,"code":361,"markDefs":12},"74d1abe74dee","package main\nimport \"fmt\"\nfunc main() {\n   fmt.Println(\"hello world\")\n}\n",{"_key":363,"_type":291,"code":364,"markDefs":12},"92ab2e23c6b8","$ go build\n    > 1,5M",{"_key":366,"_type":68,"children":367,"markDefs":372,"style":88},"8751f9f869b1",[368],{"_key":369,"_type":72,"marks":370,"text":371},"8751f9f869b10",[],"Snippet 3: C “hello world”",[],{"_key":374,"_type":291,"code":375,"markDefs":12},"f46af5191ae8","#include \u003Cstdio.h>\nint main(void)\n{\n  printf(\"hello world\\n\");\n  return 0;\n}",{"_key":377,"_type":291,"code":378,"markDefs":12},"9f926e3562bc","$ gcc main.c \n> 8,5K\n$ ldd a.out \n> linux-vdso.so.1\n> libc.so.6\n> \u002Flib64\u002Fld-linux-x86-64.so.2\n$ gcc -static main.c \n> 892K\n$ gcc -static main.c & strip\n> 821K\n",{"_key":380,"_type":68,"children":381,"markDefs":386,"style":280},"42078dd065cf",[382],{"_key":383,"_type":72,"marks":384,"text":385},"42078dd065cf0",[],"Speed comparison of Go vs. C",[],{"_key":388,"_type":68,"children":389,"markDefs":402,"style":88},"083c550f4ea3",[390,394,398],{"_key":391,"_type":72,"marks":392,"text":393},"083c550f4ea30",[],"Compiled Go code is generally slower than C executables. Go is fully garbage collected and this itself slows things down. With C, you can decide precisely where you want to allocate memory for the variables and whether that is on the stack or on the heap. With Go, the compiler tries to make an educated decision on where to allocate the variables. You can see where the variables will be allocated (",{"_key":395,"_type":72,"marks":396,"text":397},"083c550f4ea31",[291],"go build -gcflags -m",{"_key":399,"_type":72,"marks":400,"text":401},"083c550f4ea32",[],"), but you cannot force the compiler to use only the stack, for example.",[],{"_key":404,"_type":68,"children":405,"markDefs":410,"style":88},"e8527cac0971",[406],{"_key":407,"_type":72,"marks":408,"text":409},"e8527cac09710",[],"However, when it comes to speed we can not forget about compilation speed and developer speed. Go provides extremely fast compilation; for example, 15,000 lines of Go client code takes 1.4 seconds to compile. Go is very well designed for concurrent execution (goroutines and channels) and the aforementioned rich standard library covers most of the basic needs, so development is faster.",[],{"_key":412,"_type":68,"children":413,"markDefs":418,"style":280},"9c00800d1998",[414],{"_key":415,"_type":72,"marks":416,"text":417},"9c00800d19980",[],"Compilation and cross compilation",[],{"_key":420,"_type":68,"children":421,"markDefs":466,"style":88},"17bbebb01553",[422,426,430,434,438,442,445,449,453,457,462],{"_key":423,"_type":72,"marks":424,"text":425},"17bbebb015530",[],"There are two Go compilers you can use: the original one is called ",{"_key":427,"_type":72,"marks":428,"text":429},"17bbebb015531",[291],"gc",{"_key":431,"_type":72,"marks":432,"text":433},"17bbebb015532",[],". It is part of the default installation and is written and maintained by Google. The second is called ",{"_key":435,"_type":72,"marks":436,"text":437},"17bbebb015533",[291],"gccgo",{"_key":439,"_type":72,"marks":440,"text":441},"17bbebb015534",[]," and is a frontend for GCC. With ",{"_key":443,"_type":72,"marks":444,"text":437},"17bbebb015535",[291],{"_key":446,"_type":72,"marks":447,"text":448},"17bbebb015536",[],", compilation is extremely fast and large modules can be compiled within seconds. As mentioned already, Go by default compiles statically so that a single binary is created with no extra dependencies or need for virtual machines. It is possible to create and use shared libraries using the ",{"_key":450,"_type":72,"marks":451,"text":452},"17bbebb015537",[291],"-linkshared",{"_key":454,"_type":72,"marks":455,"text":456},"17bbebb015538",[]," flag. Ordinarily, Go requires no build files and a build can be carried out by a simple \"go build\" command, but it is also possible to use a Makefile for more advanced build procedures. Here’s the ",{"_key":458,"_type":72,"marks":459,"text":461},"17bbebb015539",[460],"8a7bd01d4906","Makefile",{"_key":463,"_type":72,"marks":464,"text":465},"17bbebb0155310",[]," we use at Mender.",[467],{"_key":460,"_type":86,"href":468,"reference":12},"https:\u002F\u002Fgithub.com\u002Fmendersoftware\u002Fmender\u002Fblob\u002Fmaster\u002FMakefile",{"_key":470,"_type":68,"children":471,"markDefs":484,"style":88},"ccc80920c0c4",[472,476,480],{"_key":473,"_type":72,"marks":474,"text":475},"ccc80920c0c40",[],"On top of the above, Go supports a large number of OSes and architectures when it comes to cross compilation. ",{"_key":477,"_type":72,"marks":478,"text":479},"ccc80920c0c41",[217],"Figure 3",{"_key":481,"_type":72,"marks":482,"text":483},"ccc80920c0c42",[]," highlights the wide array of OSs and platforms supported by Go.",[],{"_key":486,"_type":68,"children":487,"markDefs":591,"style":88},"3c21b6a6be18",[488,492,496,500,504,508,512,516,519,523,527,531,534,538,541,545,548,552,556,560,563,567,570,574,577,581,584,588],{"_key":489,"_type":72,"marks":490,"text":491},"3c21b6a6be180",[217],"GO OS \u002F GO ARCHamd64386armarm64ppc64leppc64mips64lemips64mipslemipswasmrisc64aix",{"_key":493,"_type":72,"marks":494,"text":495},"3c21b6a6be181",[],"X",{"_key":497,"_type":72,"marks":498,"text":499},"3c21b6a6be182",[217],"android",{"_key":501,"_type":72,"marks":502,"text":503},"3c21b6a6be183",[],"XXXX",{"_key":505,"_type":72,"marks":506,"text":507},"3c21b6a6be184",[217],"darwin",{"_key":509,"_type":72,"marks":510,"text":511},"3c21b6a6be185",[],"XX",{"_key":513,"_type":72,"marks":514,"text":515},"3c21b6a6be186",[217],"dragonfly",{"_key":517,"_type":72,"marks":518,"text":495},"3c21b6a6be187",[],{"_key":520,"_type":72,"marks":521,"text":522},"3c21b6a6be188",[217],"freebsd",{"_key":524,"_type":72,"marks":525,"text":526},"3c21b6a6be189",[],"XXX",{"_key":528,"_type":72,"marks":529,"text":530},"3c21b6a6be1810",[217],"illumos",{"_key":532,"_type":72,"marks":533,"text":495},"3c21b6a6be1811",[],{"_key":535,"_type":72,"marks":536,"text":537},"3c21b6a6be1812",[217],"ios",{"_key":539,"_type":72,"marks":540,"text":495},"3c21b6a6be1813",[],{"_key":542,"_type":72,"marks":543,"text":544},"3c21b6a6be1814",[217],"js",{"_key":546,"_type":72,"marks":547,"text":495},"3c21b6a6be1815",[],{"_key":549,"_type":72,"marks":550,"text":551},"3c21b6a6be1816",[217],"linux",{"_key":553,"_type":72,"marks":554,"text":555},"3c21b6a6be1817",[],"XXXXXXXXXXX",{"_key":557,"_type":72,"marks":558,"text":559},"3c21b6a6be1818",[217],"netbsd",{"_key":561,"_type":72,"marks":562,"text":526},"3c21b6a6be1819",[],{"_key":564,"_type":72,"marks":565,"text":566},"3c21b6a6be1820",[217],"openbsd",{"_key":568,"_type":72,"marks":569,"text":503},"3c21b6a6be1821",[],{"_key":571,"_type":72,"marks":572,"text":573},"3c21b6a6be1822",[217],"plan9",{"_key":575,"_type":72,"marks":576,"text":526},"3c21b6a6be1823",[],{"_key":578,"_type":72,"marks":579,"text":580},"3c21b6a6be1824",[217],"solaris",{"_key":582,"_type":72,"marks":583,"text":495},"3c21b6a6be1825",[],{"_key":585,"_type":72,"marks":586,"text":587},"3c21b6a6be1826",[217],"windows",{"_key":589,"_type":72,"marks":590,"text":503},"3c21b6a6be1827",[],[],{"_key":593,"_type":68,"children":594,"markDefs":599,"style":280},"7b7048831ad3",[595],{"_key":596,"_type":72,"marks":597,"text":598},"7b7048831ad30",[],"Debugging and testing in Go",[],{"_key":601,"_type":68,"children":602,"markDefs":625,"style":88},"134c93a709e2",[603,607,612,616,621],{"_key":604,"_type":72,"marks":605,"text":606},"134c93a709e20",[],"Many developers, in order to see what’s going on within a program while it executes, will use ",{"_key":608,"_type":72,"marks":609,"text":611},"134c93a709e21",[610],"ae7cf11bb049","GDB",{"_key":613,"_type":72,"marks":614,"text":615},"134c93a709e22",[],". For heavily concurrent Go applications, GDB has some issues in trying to debug them. Fortunately, there is a dedicated Go debugger called ",{"_key":617,"_type":72,"marks":618,"text":620},"134c93a709e23",[619],"207878fd8b7a","Delve",{"_key":622,"_type":72,"marks":623,"text":624},"134c93a709e24",[]," that is more suitable for this purpose. Developers only familiar with GDB should be able to use it in majority of cases without any issues",[626,628],{"_key":610,"_type":86,"href":627,"reference":12},"https:\u002F\u002Fwww.sourceware.org\u002Fgdb\u002F",{"_key":619,"_type":86,"href":629,"reference":12},"https:\u002F\u002Fgithub.com\u002Fderekparker\u002Fdelve",{"_key":631,"_type":68,"children":632,"markDefs":637,"style":88},"f715f7684b0c",[633],{"_key":634,"_type":72,"marks":635,"text":636},"f715f7684b0c0",[],"It is extremely easy to add testing and unit testing to Go code. Testing is built into the language—all that is needed is to create a file with a “test” suffix, add a test prefix to your function, import the testing package, and then run “go test”. All your tests will be automatically picked up from your source and executed accordingly.",[],{"_key":639,"_type":68,"children":640,"markDefs":645,"style":280},"b28e0683fa44",[641],{"_key":642,"_type":72,"marks":643,"text":644},"b28e0683fa440",[],"Concurrency support",[],{"_key":647,"_type":68,"children":648,"markDefs":653,"style":88},"befbfb9251e7",[649],{"_key":650,"_type":72,"marks":651,"text":652},"befbfb9251e70",[],"Concurrency is well supported in Go. It has two built-in mechanisms: goroutines and channels. goroutines are lightweight threads just 2 kB in size. It is very easy to create a goroutine: you only need to add the “go” keyword in front of the function and it will execute concurrently. Go has its own internal scheduler, and goroutines can be multiplexed into OS threads as required . Channels are “pipes'' for exchanging messages between goroutines, which can be either blocking and non-blocking.",[],{"_key":655,"_type":68,"children":656,"markDefs":661,"style":124},"08d4839df432",[657],{"_key":658,"_type":72,"marks":659,"text":660},"08d4839df4320",[],"Static and dynamic libraries; C code in Go",[],{"_key":663,"_type":68,"children":664,"markDefs":684,"style":88},"4dbf70938ccd",[665,669,673,677,680],{"_key":666,"_type":72,"marks":667,"text":668},"4dbf70938ccd0",[],"Go has many less known features that allow you to pass instructions to the compiler, linker, and other parts of the toolchain using special flags. These include the ",{"_key":670,"_type":72,"marks":671,"text":672},"4dbf70938ccd1",[291],"-buildmode",{"_key":674,"_type":72,"marks":675,"text":676},"4dbf70938ccd2",[]," and ",{"_key":678,"_type":72,"marks":679,"text":452},"4dbf70938ccd3",[291],{"_key":681,"_type":72,"marks":682,"text":683},"4dbf70938ccd4",[]," flags, which can be used to create and use static and dynamic libraries both for Go and C snippets. With a combination of specific flags, you can create static or dynamic libraries with generated header files for C, which can be invoked by C code later on.",[],{"_key":686,"_type":68,"children":687,"markDefs":692,"style":88},"2538b8b6f167",[688],{"_key":689,"_type":72,"marks":690,"text":691},"2538b8b6f1670",[],"That’s right! With Go we can call C code and have the best of both worlds. The cgo tool, which is part of the Go distribution, can execute C code, which makes it possible to reuse our own or system C libraries. In fact, cgo and implicit usage of C system libraries is more popular than one might think. There are cases when standard C library routines are picked over pure Go implementations by the Go language constructs themselves.",[],{"_key":694,"_type":68,"children":695,"markDefs":746,"style":88},"bcdfcbe03f6e",[696,700,704,707,711,715,719,722,726,730,734,738,742],{"_key":697,"_type":72,"marks":698,"text":699},"bcdfcbe03f6e0",[],"For example, when using a network package on Unix systems, there is a big chance that a cgo-based resolver will be picked. It happens to call C library routines (",{"_key":701,"_type":72,"marks":702,"text":703},"bcdfcbe03f6e1",[291],"getaddrinfo",{"_key":705,"_type":72,"marks":706,"text":676},"bcdfcbe03f6e2",[],{"_key":708,"_type":72,"marks":709,"text":710},"bcdfcbe03f6e3",[291],"getnameinfo",{"_key":712,"_type":72,"marks":713,"text":714},"bcdfcbe03f6e4",[],") for resolving names in cases when native Go resolver can not be used (for example on OS X when direct DNS calls are not allowed). Another common case might be when the os\u002Fuser package is used. If you want to skip building cgo parts you can pass ",{"_key":716,"_type":72,"marks":717,"text":718},"bcdfcbe03f6e5",[291],"osusergo",{"_key":720,"_type":72,"marks":721,"text":676},"bcdfcbe03f6e6",[],{"_key":723,"_type":72,"marks":724,"text":725},"bcdfcbe03f6e7",[291],"netgo",{"_key":727,"_type":72,"marks":728,"text":729},"bcdfcbe03f6e8",[]," tags (",{"_key":731,"_type":72,"marks":732,"text":733},"bcdfcbe03f6e9",[291],"go build -tags osusergo,netgo",{"_key":735,"_type":72,"marks":736,"text":737},"bcdfcbe03f6e10",[],") or disable cgo completely with ",{"_key":739,"_type":72,"marks":740,"text":741},"bcdfcbe03f6e11",[291],"CGO_ENABLED=0",{"_key":743,"_type":72,"marks":744,"text":745},"bcdfcbe03f6e12",[]," variable.",[],{"_key":748,"_type":68,"children":749,"markDefs":754,"style":88},"7c50f36a2df9",[750],{"_key":751,"_type":72,"marks":752,"text":753},"7c50f36a2df90",[],"There are tricky things to look out for when mixing C and Go together. Because Go is garbage collected but C is not, so if you are using any C variables within Go code that are allocated on the heap in the C code, then you need to explicitly free those variables inside Go.",[],{"_key":756,"_type":68,"children":757,"markDefs":762,"style":88},"428fe57b0199",[758],{"_key":759,"_type":72,"marks":760,"text":761},"428fe57b01990",[],"C++ can also be used inside Go code, which is facilitated through a simplified wrapper and interface generator (SWIG) that binds C and C++ with languages such as Python.",[],{"_key":764,"_type":68,"children":765,"markDefs":770,"style":124},"4b033e4e2b78",[766],{"_key":767,"_type":72,"marks":768,"text":769},"4b033e4e2b780",[],"Go advantages outweigh the disadvantages",[],{"_key":772,"_type":68,"children":773,"markDefs":778,"style":88},"b6f8db270bc9",[774],{"_key":775,"_type":72,"marks":776,"text":777},"b6f8db270bc90",[],"Our experience using Go shows both advantages and disadvantages. Starting with the negatives, there are a lot of external libraries in the community but the quality varies greatly and you need to be very careful with what kinds of libraries you use. This is improving greatly as the language matures and gains adoption.",[],{"_key":780,"_type":68,"children":781,"markDefs":786,"style":88},"81529355860c",[782],{"_key":783,"_type":72,"marks":784,"text":785},"81529355860c0",[],"When you have some C bindings within your Go code, things usually get more complicated, especially cross compiling, which cannot be done easily without importing the whole C cross-compilation infrastructure.",[],{"_key":788,"_type":68,"children":789,"markDefs":814,"style":88},"7e1971265401",[790,794,798,802,806,810],{"_key":791,"_type":72,"marks":792,"text":793},"7e19712654010",[],"There are still a lot of positives about using Go for embedded development. It’s quick and easy to transition from C and\u002For Python to Go and get productive within a couple of days. Go offers very nice tooling and a standard library with more than 100 packages. You can easily set and control runtime settings such as how many OS threads you want to use (",{"_key":795,"_type":72,"marks":796,"text":797},"7e19712654011",[217,291],"GOMAXPROCS",{"_key":799,"_type":72,"marks":800,"text":801},"7e19712654012",[],"), or if you want to switch on or off garbage collection (",{"_key":803,"_type":72,"marks":804,"text":805},"7e19712654013",[291,217],"GOGC",{"_key":807,"_type":72,"marks":808,"text":809},"7e19712654014",[291],"=off",{"_key":811,"_type":72,"marks":812,"text":813},"7e19712654015",[],"). Libraries and code can be shared easily between the server and client development teams like in our case.",[],{"_key":816,"_type":68,"children":817,"markDefs":822,"style":88},"d430f659d695",[818],{"_key":819,"_type":72,"marks":820,"text":821},"d430f659d6950",[],"It may be controversial to say this, but the forced coding standard speeds up development. Regardless of the code you are inspecting, it always looks the same. There is no time wasted wondering which coding standard to use.",[],{"_key":824,"_type":68,"children":825,"markDefs":839,"style":88},"045167354ecf",[826,830,835],{"_key":827,"_type":72,"marks":828,"text":829},"045167354ecf0",[],"We developed a few demos of embedded Go applications that you can play with using popular hardware such as Beaglebone Black or Raspberry Pi: One is called “",{"_key":831,"_type":72,"marks":832,"text":834},"045167354ecf1",[833],"1693f9055951","Thermostat",{"_key":836,"_type":72,"marks":837,"text":838},"045167354ecf2",[],"” and is based on Beaglebone hardware. It uses infrared distance, temperature, and humidity sensors and exports all the sensor readings through a web interface. The other one is a PRi-based robot car with a camera that can be controlled using a provided web interface. Enjoy!",[840],{"_key":833,"_type":86,"href":841,"reference":12},"https:\u002F\u002Fgithub.com\u002Fmendersoftware\u002Fthermostat",{"_key":843,"_type":68,"children":844,"markDefs":866,"style":88},"3e4a19b47ec2",[845,850,854,858,863],{"_key":846,"_type":72,"marks":847,"text":849},"3e4a19b47ec20",[848],"em","Marcin Pasinski is the Chief Embedded Engineer at ",{"_key":851,"_type":72,"marks":852,"text":79},"3e4a19b47ec21",[853,848],"7082daf2d3af",{"_key":855,"_type":72,"marks":856,"text":857},"3e4a19b47ec22",[848],". If you want to learn more about the best approaches to over-the-air software updates for IoT gateway devices, visit Mender.io and try the OTA software updater for ",{"_key":859,"_type":72,"marks":860,"text":862},"3e4a19b47ec23",[861,848],"92a22f12f2f4","free",{"_key":864,"_type":72,"marks":865,"text":320},"3e4a19b47ec24",[848],[867,868],{"_key":853,"_type":86,"href":87,"reference":12},{"_key":861,"_type":86,"href":869,"reference":12},"https:\u002F\u002Fhosted.mender.io\u002Fui\u002F#\u002Fsignup",true,"2022\u002F04\u002F04","Impossibly tight deadlines, unrealistic schedules, and constant pressure to develop and release applications on time, while at the same time achieving excellent quality. Sound familiar?",{"_type":56,"asset":874},{"_ref":875,"_type":59},"image-cfb53d915cb584327b27b4749bdfc42c1de02242-2400x1260-jpg",{"code":877,"language":878},"\u003C!-- wp:paragraph -->\n\u003Cp>Impossibly tight deadlines, unrealistic schedules, and constant pressure to develop and release applications on time, while at the same time achieving excellent quality. Sound familiar? Faster time-to-market for embedded applications is indeed a critical consideration for embedded development teams. But how do you develop an approach for delivering applications faster while maintaining quality and security as a priority? In this context, the product engineering team behind the OTA software update manager \u003Ca href=\"https:\u002F\u002Fmender.io\u002F\">Mender.io\u003C\u002Fa>, went through the process of selecting the best programming language for developing both the embedded client and server parts of Mender. In this evaluation process Go, C, and C++ were shortlisted as candidates. Some of the lessons learned from this evaluation process are explained and why Go was ultimately selected to develop Mender’s client embedded application.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>While this can be quite subjective, \u003Ca href=\"https:\u002F\u002Fstackoverflow.blog\u002F2020\u002F11\u002F02\u002Fgo-golang-learn-fast-programming-languages\u002F\">Go\u003C\u002Fa> can be a very productive language for embedded development. This is especially true when it comes to network programming, which is at some point a part of every connected device or application. Go was created by Google to meet the needs of Google developers, and it was mainly developed to try to fix the explosion of complexity within its ecosystem. So efficient compilation, efficient execution, and ease of programming were the three main principles behind developing Go as not all three were available before in the same mainstream language.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>However, we want to stress that Go cannot be considered a replacement for C as there are many places where C is and likely will be needed, such as in the development of real time operating systems or device drivers.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-strict-requirements-for-embedded-development\">Strict requirements for embedded development\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>After establishing the architecture, the Mender product engineering team evaluated which language would be the best fit to develop the Mender application. The system was supposed to consist of a client running on the embedded device and server acting as a central point where clients were connected to. As such, we had several requirements for the language:&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>As the client application would be running on embedded devices, compiled binaries needed to be as small as possible.&nbsp;\u003C\u002Fli>\u003Cli>It needed to work with Yocto, the embedded distribution of Linux.\u003C\u002Fli>\u003Cli>The complexity of installation clients should be low, thus limiting external dependencies and libraries.\u003C\u002Fli>\u003Cli>As it would run on different devices, the language must compile across different architectures.&nbsp;\u003C\u002Fli>\u003Cli>The devices that the Mender client application would run on would be an IoT or networked device, so the language needed access to networking libraries.&nbsp;\u003C\u002Fli>\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The requirements for selecting a new language also covered a few non-functional requirements:&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>As many programmers as possible within our organization needed to be able to understand the language.&nbsp;\u003C\u002Fli>\u003Cli>It had to be as easy as possible to share and reuse the existing code between existing applications written in C and reuse&nbsp; code between the client and server applications.&nbsp;\u003C\u002Fli>\u003Cli>Development speed was also considered—we have ongoing pressure to add new features quickly.&nbsp;\u003C\u002Fli>\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>A comparison between Go, C, and C++ is outlined in \u003Cstrong>Figure 1\u003C\u002Fstrong>. From the comparison, Go was primarily selected for its support of buffer overflow protection, automatic memory management, use of standard data containers, and its integrated support for JSON, HTTP, and SSL\u002FTLS libraries.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:table -->\n\u003Cfigure class=\"wp-block-table\">\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>Requirement\u003C\u002Ftd>\u003Ctd>C\u003C\u002Ftd>\u003Ctd>C++\u003C\u002Ftd>\u003Ctd>Go\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Size requirements in devices\u003C\u002Ftd>\u003Ctd>Lowest\u003C\u002Ftd>\u003Ctd>Low (1.8MB more)\u003C\u002Ftd>\u003Ctd>Low (2.1 MB more, however will increase with more binaries)\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Setup requirements in Yocto\u003C\u002Ftd>\u003Ctd>None\u003C\u002Ftd>\u003Ctd>None\u003C\u002Ftd>\u003Ctd>None\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Buffer under\u002Foverflow protection\u003C\u002Ftd>\u003Ctd>None\u003C\u002Ftd>\u003Ctd>Little\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Code reuse\u002Fsharing from CFEngine\u003C\u002Ftd>\u003Ctd>Good\u003C\u002Ftd>\u003Ctd>Easy (full backwards compatibility)\u003C\u002Ftd>\u003Ctd>Can import C API\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Automatic memory management\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003Ctd>Available, but not enforced\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Standard data containers\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>JSON\u003C\u002Ftd>\u003Ctd>json-c\u003C\u002Ftd>\u003Ctd>jsoncpp\u003C\u002Ftd>\u003Ctd>Built-in\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>HTTP library\u003C\u002Ftd>\u003Ctd>curl\u003C\u002Ftd>\u003Ctd>curl\u003C\u002Ftd>\u003Ctd>Built-in\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>SSL\u002FTLS\u003C\u002Ftd>\u003Ctd>OpenSSL\u003C\u002Ftd>\u003Ctd>OpenSSL\u003C\u002Ftd>\u003Ctd>Built-in (TLS is a part of crypto\u002Ftls package)*\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cfigcaption>Figure 1: A table comparison of features across Go, C, and C++&nbsp;\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:table -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The evaluation continued to see how Go would stack up against C, C++, and C++\u002FQt for creating a full-blown custom Linux image using Yocto. Pure image size and image size with network stack were compared, as was how the end application would be delivered to a target image.&nbsp; As Go applications can be statically compiled to a single binary, there is no need for any extra virtual environment (like in the case of Java, which requires a virtual machine in addition to binaries) or additional dependencies running on the device to use the Go code.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:table -->\n\u003Cfigure class=\"wp-block-table\">\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003C\u002Ftd>\u003Ctd>C\u003C\u002Ftd>\u003Ctd>C++\u003C\u002Ftd>\u003Ctd>C++\u002FQt\u003C\u002Ftd>\u003Ctd>Go\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Size overhead of the test component, and all the new libraries pulled in, when using the smallest available Yocto image as a basis\u003C\u002Ftd>\u003Ctd>8.4MB\u003C\u002Ftd>\u003Ctd>10.2MB\u003C\u002Ftd>\u003Ctd>20.8MB\u003C\u002Ftd>\u003Ctd>14.6MB\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Size with network stack\u003C\u002Ftd>\u003Ctd>13.4MB (curl)\u003C\u002Ftd>\u003Ctd>15.2MB (curl)\u003C\u002Ftd>\u003Ctd>20.8MB*\u003C\u002Ftd>\u003Ctd>14.6MB\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Shared dependencies\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Extra Yocto layer needed\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Deployment complexity\u003C\u002Ftd>\u003Ctd>Binary\u003C\u002Ftd>\u003Ctd>Binary\u003C\u002Ftd>\u003Ctd>Binary + Qt\u003C\u002Ftd>\u003Ctd>Binary\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cfigcaption>Figure 2: How Go compares to other programming languages for Yocto builds\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:table -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-comparing-go-vs-c\">Comparing Go vs. C\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Go was also selected for development due to its extremely rich standard library, which allows for much faster development, especially when compared to C. Go inherits a lot of elements from C, C++, and Python including the expression syntax, control flow statements, data structures, interfaces, pointers, the pass by value concept, parameter parsing syntax, string handling, and garbage collection. With its optimized compiler, Go runs natively on embedded devices.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Go did have some disadvantages, which we’ll mention below. They didn’t weigh heavily enough to overcome its advantages, like the development speed and ease of building in the language, but they did factor into our decision. Here’s the other qualities that went into our decision.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-size-comparison-of-go-vs-c\">Size comparison of Go vs. C\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Go is bulkier than C when it comes to size, which was one of the few disadvantages it had. If you take “hello world” as the smallest application you can write in Go and use the built-in \u003Ccode>println\u003C\u002Fcode> function, after stripping away debugging symbols it is just over 600 kB in size\u003Cstrong> (snippet 1)\u003C\u002Fstrong>. If you include the \u003Ccode>fmt\u003C\u002Fcode> package with its dependencies, then the size increases to 1.5 MB \u003Cstrong>(snippet 2)\u003C\u002Fstrong>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>To compare this to C, if you are building a dynamically linked library, then it is a mere 8 kbytes. If you do it static, then the size increases to over 800 kbytes which is surprisingly even larger than the Go binary \u003Cstrong>(snippet 3)\u003C\u002Fstrong>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Snippet 1: smallest Go “hello world” code:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>package main\nfunc main() {\n   println(\"hello world\")\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>$ go build\n     &gt; 938K\n$ go build -ldflags ‘-s -w’\n     &gt; 682K\n$ go build &amp; strip\n     &gt; 623K\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Snippet 2:&nbsp; Go “standard” “hello world”\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>package main\nimport \"fmt\"\nfunc main() {\n   fmt.Println(\"hello world\")\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>$ go build\n    &gt; 1,5M\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Snippet 3:&nbsp; C “hello world”\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>#include &lt;stdio.h&gt;\nint main(void)\n{\n  printf(\"hello world\\n\");\n  return 0;\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>$ gcc main.c \n&gt; 8,5K\n$ ldd a.out \n&gt; linux-vdso.so.1\n&gt; libc.so.6\n&gt; \u002Flib64\u002Fld-linux-x86-64.so.2\n$ gcc -static main.c \n&gt; 892K\n$ gcc -static main.c &amp; strip\n&gt; 821K\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-speed-comparison-of-go-vs-c\">Speed comparison of Go vs. C\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Compiled Go code is generally slower than C executables. Go is fully garbage collected and this itself slows things down. With C, you can decide precisely where you want to allocate memory for the variables and whether that is on the stack or on the heap. With Go, the compiler tries to make an educated decision on where to allocate the variables. You can see where the variables will be allocated (\u003Ccode>go build -gcflags -m\u003C\u002Fcode>), but you cannot force the compiler to use only the stack, for example.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>However, when it comes to speed we can not forget about compilation speed and developer speed. Go provides extremely fast compilation; for example, 15,000 lines of Go client code takes 1.4 seconds to compile. Go is very well designed for&nbsp; concurrent execution (goroutines and channels) and the aforementioned rich standard library covers most of the basic needs, so development is faster.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-compilation-and-cross-compilation\">Compilation and cross compilation\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are two Go compilers you can use: the original one is called \u003Ccode>gc\u003C\u002Fcode>. It is part of the default installation and is written and maintained by Google. The second is called \u003Ccode>gccgo\u003C\u002Fcode> and is a frontend for GCC. With \u003Ccode>gccgo\u003C\u002Fcode>, compilation is extremely fast and large modules can be compiled within seconds. As mentioned already, Go by default compiles statically so that a single binary is created with no extra dependencies or need for virtual machines. It is possible to create and use shared libraries using the \u003Ccode>-linkshared\u003C\u002Fcode> flag. Ordinarily, Go requires no build files and a build can be carried out by a simple \"go build\" command, but it is also possible to use a Makefile for more advanced build procedures. Here’s the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fmendersoftware\u002Fmender\u002Fblob\u002Fmaster\u002FMakefile\">Makefile\u003C\u002Fa> we use at Mender.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>On top of the above, Go supports a large number of OSes and architectures when it comes to cross compilation. \u003Cstrong>Figure 3\u003C\u002Fstrong> highlights the wide array of OSs and platforms supported by Go.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:table -->\n\u003Cfigure class=\"wp-block-table\">\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cstrong>GO OS \u002F GO ARCH\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>amd64\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>386\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>arm\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>arm64\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>ppc64le\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>ppc64\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>mips64le\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>mips64\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>mipsle\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>mips\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>wasm\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>risc64\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>aix\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>android\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>darwin\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>dragonfly\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>freebsd\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>illumos\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>ios\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>js\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>linux\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>netbsd\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>openbsd\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>plan9\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>solaris\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>windows\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>X\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003Ctd>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:table -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-debugging-and-testing-in-go\">Debugging and testing in Go\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Many developers, in order to see what’s going on within a program while it executes, will use \u003Ca href=\"https:\u002F\u002Fwww.sourceware.org\u002Fgdb\u002F\">GDB\u003C\u002Fa>.&nbsp; For heavily concurrent Go applications, GDB has some issues in trying to debug them. Fortunately, there is a dedicated Go debugger called \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fderekparker\u002Fdelve\">Delve\u003C\u002Fa> that is more suitable for this purpose. Developers only familiar with GDB should&nbsp; be able to use it in majority of cases without any issues\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>It is extremely easy to add testing and unit testing to Go code. Testing is built into the language—all that is needed is to create a file with a “test” suffix, add a test prefix to your function, import the testing package, and then run “go test”. All your tests will be automatically picked up from your source and executed accordingly.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-concurrency-support\">Concurrency support\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Concurrency is well supported in Go. It has two built-in mechanisms: goroutines and channels. goroutines are lightweight threads just 2 kB in size.&nbsp; It is very easy to create a goroutine: you only need to add the “go” keyword in front of the function and it will execute concurrently. Go has its own internal scheduler, and goroutines can be multiplexed into OS threads as required . Channels are “pipes'' for exchanging messages between goroutines, which can be either blocking and non-blocking.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-static-and-dynamic-libraries-c-code-in-go\">Static and dynamic libraries; C code in Go\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Go has many less known features that allow you to pass instructions to the compiler, linker, and other parts of the toolchain using special flags. These include the&nbsp; \u003Ccode>-buildmode\u003C\u002Fcode> and \u003Ccode>-linkshared\u003C\u002Fcode> flags, which can be used to create and use static and dynamic libraries both for Go and C snippets. With a combination of specific flags, you can create static or dynamic libraries with generated header files for C, which can be invoked by C code later on.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>That’s right! With Go we can call C code and have the best of both worlds. The cgo tool, which is part of the Go distribution, can execute C code, which makes it possible to reuse our own or system C libraries. In fact, cgo and implicit usage of C system libraries is more popular than one might think. There are cases when standard C library routines are picked over pure Go implementations by the Go language constructs themselves.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For example, when using a network package on Unix systems, there is a big chance that a cgo-based resolver will be picked. It happens to call C library routines (\u003Ccode>getaddrinfo\u003C\u002Fcode> and \u003Ccode>getnameinfo\u003C\u002Fcode>) for resolving names in cases when native Go resolver can not be used (for example on OS X when direct DNS calls are not allowed). Another common case might be when the os\u002Fuser package is used. If you want to skip building cgo parts you can pass \u003Ccode>osusergo\u003C\u002Fcode> and \u003Ccode>netgo\u003C\u002Fcode> tags (\u003Ccode>go build -tags osusergo,netgo\u003C\u002Fcode>) or disable cgo completely with \u003Ccode>CGO_ENABLED=0\u003C\u002Fcode> variable.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are tricky things to look out for when mixing C and Go together. Because Go is garbage collected but C is not, so if you are using any C variables within Go code that are allocated on the heap in the C code, then you need to explicitly free those variables inside Go.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>C++ can also be used inside Go code, which is facilitated through a simplified wrapper and interface generator (SWIG) that binds C and C++ with languages such as Python.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-go-advantages-outweigh-the-disadvantages\">Go advantages outweigh the disadvantages\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Our experience using Go shows both advantages and disadvantages. Starting with the negatives, there are a lot of external libraries in the community but the quality varies greatly and you need to be very careful with what kinds of libraries you use. This is improving greatly as the language matures and gains adoption.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When you have some C bindings within your Go code, things usually get more complicated, especially cross compiling, which cannot be done easily without importing the whole C cross-compilation infrastructure.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are still a lot of positives about using Go for embedded development. It’s quick and easy to transition from C and\u002For Python to Go and get productive within a couple of days. Go offers very nice tooling and a standard library with more than 100 packages. You can easily set and control runtime settings such as how many OS threads you want to use (\u003Cstrong>\u003Ccode>GOMAXPROCS\u003C\u002Fcode>\u003C\u002Fstrong>), or if you want to switch on or off garbage collection (\u003Ccode>\u003Cstrong>GOGC\u003C\u002Fstrong>=off\u003C\u002Fcode>). Libraries and code can be shared easily between the server and client development teams like in our case.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>It may be controversial to say this, but the forced coding standard speeds up development. Regardless of the code you are inspecting, it always looks the same. There is no time wasted wondering which coding standard to use.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We developed a few demos of embedded Go applications that you can play with using popular hardware such as Beaglebone Black or Raspberry Pi: One is called “\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fmendersoftware\u002Fthermostat\">Thermostat\u003C\u002Fa>” and is based on Beaglebone hardware. It uses infrared distance, temperature, and humidity sensors and&nbsp; exports all the sensor readings through a web interface. The other one is a PRi-based robot car with a camera that can be controlled using a provided web interface. Enjoy!\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cem>Marcin Pasinski is the Chief Embedded Engineer at \u003C\u002Fem>\u003Ca href=\"https:\u002F\u002Fmender.io\u002F\">\u003Cem>Mender.io\u003C\u002Fem>\u003C\u002Fa>\u003Cem>. If you want to learn more about the best approaches to over-the-air software updates for IoT gateway devices, visit Mender.io and try the OTA software updater for \u003C\u002Fem>\u003Ca href=\"https:\u002F\u002Fhosted.mender.io\u002Fui\u002F#\u002Fsignup\">\u003Cem>free\u003C\u002Fem>\u003C\u002Fa>\u003Cem>.&nbsp;\u003C\u002Fem>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->","html","2022-04-04T14:00:00.000Z",{"current":881},"comparing-go-vs-c-in-embedded-applications",[883,891,896,901,905,909],{"_createdAt":884,"_id":885,"_rev":886,"_type":887,"_updatedAt":884,"slug":888,"title":890},"2023-05-23T16:43:21Z","wp-tagcat-c-2","9HpbCsT2tq0xwozQfkc4ih","blogTag",{"current":889},"c-2","c",{"_createdAt":884,"_id":892,"_rev":886,"_type":887,"_updatedAt":884,"slug":893,"title":895},"wp-tagcat-code-for-a-living",{"current":894},"code-for-a-living","Code for a Living",{"_createdAt":884,"_id":897,"_rev":886,"_type":887,"_updatedAt":884,"slug":898,"title":900},"wp-tagcat-embedded-programming",{"current":899},"embedded-programming","embedded programming",{"_createdAt":884,"_id":902,"_rev":886,"_type":887,"_updatedAt":884,"slug":903,"title":904},"wp-tagcat-go",{"current":904},"go",{"_createdAt":884,"_id":906,"_rev":886,"_type":887,"_updatedAt":884,"slug":907,"title":908},"wp-tagcat-golang",{"current":908},"golang",{"_createdAt":884,"_id":910,"_rev":886,"_type":887,"_updatedAt":884,"slug":911,"title":913},"wp-tagcat-iot",{"current":912},"iot","IoT","Comparing Go vs. C in embedded applications",[916,922,928,934],{"_id":917,"publishedAt":918,"slug":919,"sponsored":12,"title":921},"76c9771b-34e6-4d98-8641-ecefc711f0ef","2026-07-06T15:23:34.559Z",{"_type":10,"current":920},"when-the-sensor-starts-thinking-snortml-agentic-ai-and-the-evolving-architecture-of-intrusion-detection","When the sensor starts thinking: SnortML, agentic AI, and the evolving architecture of intrusion detection",{"_id":923,"publishedAt":924,"slug":925,"sponsored":12,"title":927},"28e560af-f0aa-4d46-bd90-f435ad604aa7","2026-06-26T14:00:27.102Z",{"_type":10,"current":926},"paging-charity-how-can-engineering-leaders-avoid-becoming-bond-villains","Paging Charity! How can engineering leaders avoid becoming Bond villains?",{"_id":929,"publishedAt":930,"slug":931,"sponsored":12,"title":933},"4b22c2a3-3779-4966-93eb-5230391dbdce","2026-06-23T14:08:58.595Z",{"_type":10,"current":932},"your-ai-shipped-a-backend-that-boots-that-is-the-whole-problem","Your AI shipped a backend that boots. That is the whole problem.",{"_id":935,"publishedAt":936,"slug":937,"sponsored":12,"title":939},"5cf362e1-fe7b-45af-b69c-914731c6a052","2026-06-23T14:00:00.000Z",{"_type":10,"current":938},"the-2026-developer-survey-is-now-open-for-human-developers-only","The 2026 Developer Survey is now open (for human developers only)!",{"data":941,"sourceMap":-1},{"count":942,"lastTimestamp":943},34,"2026-05-21T14:30:52Z"]