A string is one of the most-used types in software programs. Strings allow developers to display values to the user, such as showing the most important properties of an object. However, we often need additional functionality for converting strings to the desired format.
Let’s say we want to convert a floating-point number with six decimal places to a human-readable price format with only two figures after the decimal point. String formatting comes in handy here. In this guide, we’ll explore the possibilities of Go string formatting.
Golang has a rich set of string formatting options. The foremost package is the built-in fmt
package, which provides a wide variety of string formatting functionalities.
This package offers two interesting methods:
Printf
Sprintf
The first method, Printf
, prints a formatted string to os.Stdout
. However, you may want to use the formatted string to further modify or pass it to another function. Therefore, it would be useful to store the formatted string in a variable. This is exactly what Sprintf does.
s1 := fmt.Sprintf("a %s", "string")
Here, the formatted value a string
is stored in the s1
variable. In the next section, we’ll give an overview of the Golang fmt
package.
fmt
packageThe fmt
package enables you to convert strings, numbers, and even objects to a particular string format. All of the formatting options discussed below are made possible by the fmt.Printf
and fmt.Sprintf
functions.
Furthermore, modifying values happens via so-called verbs
. A verb refers to the combination of a percentage sign (%
) with a letter or number. Each verb formats a value in a different way. For this to work, the fmt.Printf
function knows how to interpret these special verbs.
For example, the %d
verb enables you to format a number to its base-10 string representation.
fmt.Printf("Number %d", 9) // Output: Number 9
There are many more interesting verbs you can use. Let’s explore a few different types, starting with general verbs.
The most important verb for printing objects is the %v
verb. It’s commonly used to quickly print an object as a string, which is helpful for debugging applications. Every Golang developer should be aware of this verb.
In the below example, a Dimension struct
is defined. This accepts two parameters: height
and length
. Next, the %v
verb prints the object’s contents.
type Dimension struct { height, length int } dimension := Dimension{180, 80} fmt.Printf("%v", dimension) // Output: {180 80}
However, those values are quite meaningless. It can be very confusing if you have a struct that holds more than five. Then you have to look up the order of each value in the struct to know which value corresponds to which field. Therefore, a little trick exists to also print the variable names. Use the %+v verb for printing your object next time as it also prints the associated fields.
fmt.Printf("%v", dimension) // Output: {height:180 length:80}
For some, it might be useful to print the type of the parameter you’re passing in. The %T
verb helps with this task. The below example prints the type for an integer.
fmt.Printf("%T", 100) // Output: int
Let’s explore different notation formats for integers. The %x
verb lets you convert an integer to a base-16 string. For example, the value 10
is represented by the letter A
in the base-16 format.
fmt.Printf("%x", 10) // Output: a
Another interesting verb is the %U
verb, which enables you to convert an integer to its Unicode representation.
fmt.Printf("%U", 10) // Output: U+000A
Many conversions are possible for floating-point numbers. These conversions are often used to display prices or other numbers with the correct number of digits after the decimal point.
The %e
verb, meanwhile, allows you to display a number in scientific notation. A number is written in scientific notation when a number between 1 and 10 is multiplied by a power of 10.
fmt.Printf("%e", 999.35) // Output: 9.993500e+02
You can convert a number to a floating-point figure with the %f
verb. By default, a floating-point number has six digits after the decimal point.
fmt.Printf("%f", 12.3456) // Output: 12.345600
However, you can use this function more usefully to convert a floating-point figure to a price tag, for example. You can pass in an extra argument that defines the number of decimals.
fmt.Printf("%.2f", 12.3456) // Output: 12.35
Notice the output here: by default, the fmt
package rounds the last digit up.
You can also pass to the %f
verb the width for the resulting string. Note that the decimal point also counts for the total width of the string.
In some cases, you might want to have a consistent length for a formatted float or add leading zeroes to your string. Currently, the length of the output 12.35
is five. Let’s set a length of six so that an extra leading zero will be printed.
fmt.Printf("%06.2f", 12.3456) // Output: 012.35
As you can see, we set the width to six by passing 06
as an extra argument, also called a flag, to the %f
verb. You always have to pass a leading zero before setting the width for your string. If you want to set the width of your string equal to 10, for example, you need to pass 010
.
fmt.Printf("%010.2f", 12.3456) // Output: 0000012.35
It’s even possible to set a negative width. Instead of adding leading zeros, you add trailing zeros. However, a negative width does not lend itself well to defining the precision.
fmt.Printf("%-010f", 12.3456) // Output: 12.345600
There are many more flags you can use to modify the output in combination with the %f
verb. You can learn more by reading the fmt
docs.
Lastly, let’s look at two useful verbs for printing strings. You may encounter escaped strings that look like this: \mystring\
. You’ll want to print this string without the escaped syntax so it looks like string
. For this, you can use the %s
verb.
fmt.Printf("%s\n", "\"string\"") // Output: "string"
In some cases, you may not want to get rid of the escaped syntax. You can use the %q
verb in those instances.
For basic string printing, use %s
.
fmt.Printf("%q\n", "\"string\"") // Output: \"string\"
Also for strings, we can pass flags such as a width for the formatted string. Here, the width of the string is created by adding leading spaces.
fmt.Printf("%10s\n", "five") // Output: five
Before we end this guide, I should mention a few important points about verbs.
%
, you can escape it with a percentage sign (you’ll get %%
).2
to a verb that doesn’t expect a flag, it will ignore the flagPrintf
and Sprintf
. You can read about them in the fmt package documentation
String literals enable you to modify a string value to ensure the string is displayed correctly.
For a simple example, let’s say you want to display a value with surrounding double-quotes. You can use a string literal for that. Backticks help encapsulate the double quotes safely.
`"My double-quoted string"`
You can do much more, such as add a line break to your string. For example, if you want to print a list of items with each item on its own line, you can use the \n
escape character.
fmt.Println("Items:\n1. Banana\n2. Apple") // Output: Items: 1. Banana 2.Apple
Another way to achieve the same result is with a multiline text block surrounded by backticks. By default, backticks allow you to create multiline strings.
fmt.Println(` Items: 1. Banana 2. Apple `) // Output: Items: 1. Banana 2.Apple
Golang offers a rich set of functions, verbs, and flags for converting any type to a string format. The most useful verb is the %+v
verb, which enables you to quickly print any object as its string representation. This is very useful for debugging your application.
Personally, I like to use the floating-point formatting options because they offer a range of possibilities for formatting a floating point to the desired string format.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.