<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sdh0x</title>
    <description>The latest articles on DEV Community by sdh0x (@sdh0x).</description>
    <link>https://dev.to/sdh0x</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4000564%2F4ce69d38-8740-4b61-b313-e237bef49ee3.png</url>
      <title>DEV Community: sdh0x</title>
      <link>https://dev.to/sdh0x</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sdh0x"/>
    <language>en</language>
    <item>
      <title>Why using strconv instead of fmt for converting typical data types to string</title>
      <dc:creator>sdh0x</dc:creator>
      <pubDate>Sun, 28 Jun 2026 11:54:51 +0000</pubDate>
      <link>https://dev.to/sdh0x/why-using-strconv-instead-of-fmt-for-converting-typical-data-types-to-string-58bj</link>
      <guid>https://dev.to/sdh0x/why-using-strconv-instead-of-fmt-for-converting-typical-data-types-to-string-58bj</guid>
      <description>&lt;h2&gt;
  
  
  Why using strconv instead of fmt for converting typical data types to string
&lt;/h2&gt;

&lt;p&gt;alot of us use &lt;code&gt;fmt.Sprint&lt;/code&gt; to convert basic data types to string, but it causes performance degradation especially if you are building a CLI utility&lt;/p&gt;

&lt;h3&gt;
  
  
  fmt.Sprint Causes Heap Escapes
&lt;/h3&gt;

&lt;p&gt;here is a code sample from go tour (i did make changes to it) that checks if X is lower than 0 , if true it formates it as a complex number formula (x + yi) &lt;br&gt;
then x goes to math.Sqrt() function to square root&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; 
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"i"&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we need then to convert the &lt;strong&gt;float64&lt;/strong&gt; to &lt;strong&gt;string&lt;/strong&gt; to show case why you should use &lt;strong&gt;strconv&lt;/strong&gt;* instead of &lt;strong&gt;fmt&lt;/strong&gt;, we used &lt;code&gt;fmt.Sprint&lt;/code&gt;, used for converting basic data types to string, this is why we called fmt twice, one for converting and one for printing the output&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we compile with the flag '-m' for the golang compiler which stands for escape analysis to instruct the compiler to print out its optimization decisions, what escaped to the heap and what stayed in the stack frame of the function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we can see that the variable str escaped to the heap besides that all in stack frame of the main function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;lost main]&lt;span class="nv"&gt;$ &lt;/span&gt;go build &lt;span class="nt"&gt;-gcflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'-m'&lt;/span&gt; main.go
&lt;span class="c"&gt;# command-line-arguments&lt;/span&gt;
./main.go:12:29: inlining call to math.Sqrt
./main.go:13:14: inlining call to fmt.Println
./main.go:15:24: inlining call to math.Sqrt
./main.go:15:14: inlining call to fmt.Println
./main.go:12:35: fmt.Sprint&lt;span class="o"&gt;(&lt;/span&gt;... argument...&lt;span class="o"&gt;)&lt;/span&gt; + &lt;span class="s2"&gt;"i"&lt;/span&gt; escapes to heap
./main.go:12:19: ... argument does not escape
./main.go:12:29: ~r0 escapes to heap
./main.go:13:14: ... argument does not escape
./main.go:13:15: str escapes to heap
./main.go:15:14: ... argument does not escape
./main.go:15:24: ~r0 escapes to heap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;str did escape to the heap, we dont need that, heap causes overload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using strconv
&lt;/h3&gt;

&lt;p&gt;strconv is the best alternative solution combined with a built in function for printing text to the terminal &lt;code&gt;println(str)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"math"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormatFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sc"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"i"&lt;/span&gt; &lt;span class="c"&gt;// 'f' stands for no exponent, take a look at strconv doc in pkg.go.dev/strconv&lt;/span&gt;
        &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormatFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sc"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if we compile with the same flag for showing the compiler optimizing decisions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;lost main]&lt;span class="nv"&gt;$ &lt;/span&gt;go build &lt;span class="nt"&gt;-gcflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'-m'&lt;/span&gt; main.go
&lt;span class="c"&gt;# command-line-arguments&lt;/span&gt;
./main.go:12:38: inlining call to math.Sqrt
./main.go:12:28: inlining call to strconv.FormatFloat
./main.go:15:20: inlining call to math.Sqrt
./main.go:12:28: inlining call to strconv.FormatFloat
./main.go:12:57: ~r0 + &lt;span class="s2"&gt;"i"&lt;/span&gt; does not escape
./main.go:12:28: string&lt;span class="o"&gt;(&lt;/span&gt;strconv.genericFtoa&lt;span class="o"&gt;(&lt;/span&gt;make&lt;span class="o"&gt;([]&lt;/span&gt;byte, 0, max&lt;span class="o"&gt;(&lt;/span&gt;strconv.prec + 4, 24&lt;span class="o"&gt;))&lt;/span&gt;, strconv.f, strconv.fmt, strconv.prec, strconv.bitSize&lt;span class="o"&gt;))&lt;/span&gt; does not escape
./main.go:12:28: make&lt;span class="o"&gt;([]&lt;/span&gt;byte, 0, max&lt;span class="o"&gt;(&lt;/span&gt;strconv.prec + 4, 24&lt;span class="o"&gt;))&lt;/span&gt; does not escape
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see, there is no "Escaped to the heap" there is only does not escape&lt;/p&gt;

&lt;h2&gt;
  
  
  why is that ?
&lt;/h2&gt;

&lt;p&gt;fmt.Sprint takes an empty &lt;strong&gt;interface{}&lt;/strong&gt; which has two-pointer structure (eface): one pointer to the dynamic type information, and one pointer to the actual data, when you pass a concrete type (float64) into fmt.Sprint go wraps it into this interface structure.&lt;/p&gt;

&lt;p&gt;Devirtualization : this is an optimization method where the compiler attempt to look through the interface, determine the type then call the method directly.&lt;/p&gt;

&lt;p&gt;Failure to Devirtualize : because fmt passes your variable down a deeply nested chain of internal functions that rely on reflection, the escape analysis algorithm completely loses visibility. ( Escape analyses is an optimization method where the compiler chooses what stays in the stack and what escapes to the heap ) it cant trace the pointers lifecycle across these interface boundaries&lt;/p&gt;

&lt;p&gt;As Safety Net the compiler cannot prove that a variable will not outlive the stack frame of the function so it cannot safely leave it on the stack, as a strict memory safety-net decision by the compiler, the variable escapes to the heap.&lt;/p&gt;

</description>
      <category>go</category>
      <category>google</category>
      <category>software</category>
    </item>
  </channel>
</rss>
