In this article we show how to work with bytes in Golang.

Go uses rune , which has type int32 , to deal with multibyte characters.

Go byte example

With the %c format verb, we print the character representation of the byte.

Because we have not set the data type explicitly, Go set a default int type.

Go string to bytes

Go bytes to string, go count bytes.

We count the number of bytes and runes of the msg string.

Go byte read file

The ioutil.ReadFile reads the specified file and returns its contents as a slice of bytes.

Go byte read binary file

Go escaped bytes.

Arbitrary character values can be encoded with backslash escapes and used in string or rune literals. Go supports a common format in which a byte is represented as \x followed by two hexadecimal values.

Go bytes functions

With Contains we check if data2 slice is a subslice of data1 .

The example joins byte slices with Join , repeats a byte slice with Repeat , and trims byte slices of the specified byte with Trim .

Go bytes.Buffer

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

Golang bytes – variable and package

Bytes are a data type in Golang. In this post, we will explore bytes as well as slices of them, the bytes package itself and what can be done with it.

What is a byte variable?

A byte in Go is simply an unsigned 8-bit integer . That means it has a limit of (0 – 255) in numerical range. In Go, a byte can represent a character from a string as well.

Creating a byte variable

The syntax for declaring a byte is really simple all is needed is to declare it as a byte variable and then use it.

Zero value of a byte

The zero value of a byte is simply zero (0).

Using bytes with strings

Bytes can be converted to and from strings in Go. This is very useful in certain cases. Here is an example of using bytes along with strings.

Golang “bytes” package

The “bytes” package implements many useful functions that can be used to manipulate byte slices. It also contains a type Buffer which is an important struct that we will be exploring later on. Here are some of the most useful functions that can be used with byte slices.

1. Compare byte slices

The Compare(b1, b2 []byte) function compares byte slices lexicographically and returns int based on the following ruleset:

2. Check if a byte slice is a subslice of other

The Contains(s, a byte[]) function is used to check if a slice is subslice of another slice. Here is an example.

3. Check if a byte slice contains the rune

The ContainsRune(b []byte, r rune) function is used to check whether a byte slice contains a rune.

4. Check for equality of byte slices

The Equal(a, b []byte) function takes two-byte slices and returns true if they are equal.

The function EqualFold checks whether two-byte slices are equal even if they are different cased.

5. The “Fields” function

The Fields function separates a byte slice by whitespace it contains.

6. The “Index” function

The index function gets the first index of occurrence of a subslice in a slice of bytes. It returns -1 if it cannot find the index.

7. Join byte slices

The join function takes an array of a byte slice and joins them with a separator that it takes as an argument.

8. The repeat function

The repeat function simply repeats the slice the number of times it gets as an argument.

9. The “Split” function

The split function uses the separator to split the string into an array of string.

10. Trimming the slice

The slice can be trimmed off anything we use by simply using the trim function. Here is the way to do that.

Go bytes.Buffer type

The buffer is a useful struct which is very efficient. The Buffer type comes with the bytes package. Here is the syntax for declaring an empty buffer.

To write into a Buffer we can use the write function like this.

The Fprintf can also be used to write into the buffer.

There are some functions that can be used with the Buffer type. This comes useful for many different scenarios. Here we are going to explore some of them.

There are multiple write functions for different types of data like strings, runes, etc in the Buffer type.

These are some of the most common use cases of bytes in Go.

What are Bytes?

Introduction to the byte in golang, encoding in bytes and strings, difference between string, byte slice and rune slice, 1. contains(b, subslice []byte) bool, 2. count(s, sep []byte) int, 3. equal(a, b []byte) bool, 4. bytes.index, 5. split(s, sep []byte) [][]byte, 6. type buffer (bytes.buffer), 7. type reader (bytes.newreader), 8.performance comparison of bytes.newreader and strings.newreader in reading 1 gb data, golang byte and bytes package.

In computing, a byte represents a unit of digital information storage that is capable of holding a single character. It consists of 8 bits and can store values ranging from 0 to 255. Bytes are the building blocks of data storage in computers and are essential for representing text, numbers, and various types of information.

In Golang programming language, the byte datatype is an alias for uint8 , which stands for an unsigned 8-bit integer. This means that:

  • Size and Range of byte : A byte in Golang occupies 8 bits of memory and can represent values ranging from 0 to 255.
  • Usage: The byte type is extensively used in Golang for handling raw binary data, reading from and writing to files, network communication, and encoding/decoding operations.

Example Usage in Golang:

In this example, the byte b is assigned the ASCII value 65 , which corresponds to the character ‘A’. Go’s ability to seamlessly handle bytes allows developers to perform such operations efficiently.

Strings and byte slice Let us understand the strings in golang briefly.

In Golang, strings are stored as a sequence of bytes that represent UTF-8 encoded characters. Each character can span multiple bytes in memory, depending on its UTF-8 encoding. Understanding how strings are stored internally in Golang provides insight into their characteristics and behaviours

  • UTF-8 Encoding:
  • In Golang, strings use UTF-8 encoding, so each character in a string is encoded using one or more bytes following the UTF-8 standard.
  • UTF-8 is a flexible encoding method where characters within the ASCII range (0-127) are encoded using one byte, but characters outside this range may be encoded using multiple bytes (up to 4 bytes per character).

To grasp strings and byte slices better, consider the example provided below.

Conversion Between Strings and Byte Slice

This example illustrates how to work with strings and byte slices in GoLang. By converting a string to a byte slice, you can see its raw byte representation. Conversely, converting a byte slice back to a string reconstructs the original string, demonstrating the relationship between these two data types in Go. This is particularly useful when handling text data that includes both ASCII and Unicode characters.

  • No Explicit Character Encoding: Bytes in Go do not carry any encoding information. They are raw data, which means their meaning is defined by the context in which they are used. This makes bytes versatile for low-level data manipulation, such as file I/O or network communication.
  • Example: The byte slice []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F} represents the ASCII characters for “Hello”. Each byte corresponds to an ASCII value: 0x48 (H), 0x65 (e), 0x6C (l), 0x6C (l), 0x6F (o).
  • UTF-8 Encoding: Go strings are inherently UTF-8 encoded, which means they can represent characters from virtually any language. UTF-8 encoding is efficient and backward-compatible with ASCII, making it suitable for a wide range of applications.
  • Example: The string unicodeString := “こんにちは” contains Japanese characters, which are encoded in UTF-8. When converted to a byte slice, each character is represented by a sequence of bytes.

Rune Data Type

In Golang, the rune data type is used to represent Unicode characters. A rune is an alias for int32, and it represents a single Unicode code point. This allows Go to support a wide range of languages and characters in strings.

String Example:

Byte Slice Example:

Run Slice Example:

In the examples above:

  • The String Example demonstrates printing a string that includes the 🙏 emoji directly.
  • The Byte Slice Example initializes a byte slice with ASCII values corresponding to “Hello” and modifies the first byte.
  • The Rune Slice Example initializes a rune slice from a string containing the 🙏 emoji and modifies the first rune.

Byte Slice ([]byte)

Rune Slice ([]rune)

Alias Names

bytes, byteArr

Representation

Characters encoded in UTF-8

Direct array of bytes

Unicode code points (int32)

Number of UTF-8 encoded bytes

Number of bytes

Number of runes

Accessible by index

Loop syntax

for index, characterValue := range string{ //code logic } Note: Inconsistent index mapping corresponding to characterValue

for index, byteValue := range byteSlice{ //code logic } Note: Consistent index mapping corresponding to byteValue

for index, runeValue := range runeSlice{ //code logic } Note: Consistent index mapping corresponding to runeValue

For a detailed understanding of strings in Golang, please visit our blog post titled Golang string .

Golang bytes package

In Golang, the bytes package provides functions and types for working with byte slice ([]byte). It offers efficient operations for manipulating byte data, buffering I/O operations, and working with strings as byte slices. Let us understand the frequently used types and function as below :

  • Function: Reports whether subslice is within b.
  • b : The byte slice to search within.
  • subslice : The byte slice to search for within b.
  • Returns: true if subslice is found within b, otherwise false .

For the complete program please visit our GitHub repository

In the above example, bytes.Contains checks if the byte slice text contains the substring subtext. Since “ample” is indeed a part of “example” , it returns true .

  • Function: Counts the number of non-overlapping instances of sep in s .
  • s : The byte slice to search within.
  • sep : The byte slice to count occurrences of within s.
  • Returns: The number of times sep occurs in s .

For the complete program, Please visit our GitHub repository.

In the above example, bytes.Count counts the occurrences of the byte e in the byte slice data. Since “e” appears twice in “example” , it returns 2 .

  • Function: Reports whether a and b are the same length and contain the same bytes.
  • a, b : The byte slices to compare.
  • Returns: true if a and b are identical in content and length, otherwise false.

bytes.Equal compares the byte slices byteSlice1 and byteSlice2 . Since both contain the same bytes (“Golang” and “Golang”) in the same order and have the same length, it returns true .

  • Function: Index(s, sep []byte) int
  • sep : The byte slice to search for within s .
  • Returns: The index of the first occurrence of sep in s, or -1 if sep is not found.

The above program uses bytes.Index to find the index of “amp” in the byte slice data, returning 2 since “amp” starts at that index in “example” . If “amp” is not found, it returns -1 .

  • Function: Splits s into slices separated by sep and returns a slice of the substrings.
  • s : The byte slice to split.
  • sep : The byte slice that specifies the delimiter.
  • Returns: A slice of byte slices ( [][]byte ) split from s based on occurrences of sep .

bytes.Split divides the byte slice data into smaller slices based on the delimiter “,” . It returns a slice ( parts ) containing three byte slices: [“apple” “banana” “orange”]

bytes.Buffer is a dynamic buffer that allows manipulation of byte data in memory. It implements the io.Reader, io.Writer, io.ReaderFrom, io.WriterTo, io.ByteScanner , and io.ByteWriter interfaces , making it highly versatile for handling byte data.

Explaination:

  • The code imports necessary packages bytes and fmt .
  • var buf bytes.Buffer creates a new bytes.Buffer named buf . This buffer will be used to store byte data.
  • buf.WriteString(“Hello, “) appends the string “Hello, “ to the buffer.
  • buf.WriteByte(‘W’) appends the byte ‘W’ to the buffer.
  • buf.Write([]byte(“orld!”)) appends the byte slice []byte(“orld!”) to the buffer.
  • After these operations, buf contains “Hello, World!” .
  • data := make([]byte, buf.Len()) creates a byte slice data with a length equal to the current length of buf .
  • buf.Read(data) reads the entire content of buf into the data slice. After this read operation, buf becomes empty because the read pointer moves to the end of the buffer.
  • fmt.Println(“Data read from buffer:”, string(data)) prints the data read from the buffer, which should be “Hello, World!” .
  • fmt.Fprintf(&buf, ” How are you?”) appends the string ” How are you?” to the buffer using fmt.Fprintf . This demonstrates using bytes.Buffer with the io.Writer interface.
  • fmt.Println(“Buffer contents:”, buf.String()) prints the entire current content of the buffer ( “Hello, World! How are you?” ).

The bytes.Buffer type in Golang provides versatile methods for working with byte data in memory. It supports efficient appending, reading, and manipulation of byte sequences, making it ideal for scenarios where dynamic construction or modification of byte data is needed, such as Building Strings Efficiently, Reading and Writing Files, Serialization and Deserialization, String Manipulation, Buffering Output , Efficient Byte Operations, Inter-process Communication.

The bytes.NewReader function in Go creates and returns a new Reader type initialized with a given byte slice b . This Reader implements the io.Reader, io.Seeker, and io.Reader At interfaces, allowing efficient reading and seeking operations on the provided byte slice.

Explanation:

  • data := []byte(“Hello, World!”): Defines a byte slice containing the string “Hello, World!”.
  • reader := bytes.NewReader(data): Creates a bytes.Reader initialized with data.
  • buffer := make([]byte, len(data)): Creates a byte slice buffer with the same length as data.
  • Example: buffer becomes [‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘,’, ‘ ‘, ‘W’, ‘o’, ‘r’, ‘l’, ‘d’, ‘!’].
  • reader.ReadByte(): Reads and returns the first byte from data, here ‘H’.
  • reader.ReadRune(): Reads and returns the first UTF-8 encoded Unicode character (rune) from data, here ‘H’.
  • reader.Seek(0, io.SeekStart): Sets the reader’s position back to the start of data.
  • reader.Reset(data): Resets the reader to read from the beginning of data.
  • var writer bytes.Buffer: Initializes a bytes.Buffer to store copied data.
  • Example: writer.String() would output “Hello, World!”.
  • Efficient Reading: Ideal for sequentially processing byte data from an in-memory source.
  • Byte and Rune Handling: Provides methods to read individual bytes and UTF-8 runes.
  • Resetting and Seeking: Supports resetting and seeking within the data for reprocessing.
  • Copying Data: Facilitates efficient copying of byte data between readers and writers.

The above example showcases how bytes.NewReader in Golang can efficiently handle and manipulate byte data, making it valuable for tasks such as parsing, processing byte-based protocols, and implementing efficient data readers in Go programs.

The provided program compares the performance of reading 1 GB of data using two different readers in Go: bytes.NewReader and strings.NewReader . This comparison helps understand the efficiency and behavior of each reader when handling large amounts of data.

Constants and Data Initialization

  • First, we define a constant GB representing 1 gigabyte in bytes. We then create a byte slice data of size 1 GB and fill it with values from 0 to 255 in a repeating pattern. This step sets up a large block of data for our read performance comparison.

Reading with bytes.NewReader

  • Next, we measure how long it takes to read the entire byte slice using bytes.NewReader. We capture the start time, create a bytes.Reader from our data, and read the data in 1024-byte chunks. We track the total bytes read and handle any read errors. Finally, we calculate the elapsed time and print the results.

Reading with strings.NewReader

  • We then perform a similar measurement using strings.NewReader. We start by converting the byte slice to a string (which involves additional memory allocation). Using a strings.Reader, we read the string data in 1024-byte chunks, tracking the total bytes read and handling errors. Again, we calculate the elapsed time and print the results.

This program compares the performance of reading 1 GB of data using bytes.NewReader and strings.NewReader . The key differences are:

  • bytes.NewReader directly reads from a byte slice.
  • strings.NewReader reads from a string, which involves converting the byte slice to a string (a more memory-intensive operation).

The program measures and prints the time taken by each reader to read the entire data, helping to understand the performance characteristics of each method.

bytes.NewReader is ideal for working with binary data. If you’re dealing with raw bytes, such as image files, network packets, or any non-textual data, bytes.NewReader provides a direct way to read and manipulate this data. If your data is textual, using strings.NewReader might be more appropriate. It provides an easy way to read and process strings, such as reading lines of text or working with string-based data formats like JSON or XML.

Reference link

To learn more about the bytes package in Golang, visit the official Golang documentation golang bytes package

golang byte assignment

Siddharth Jadhav

Leave a comment cancel reply.

Scalent Golang Services

We ❤️ Golang

  • 1. On-Demand Golang Developers / Team
  • 2. Software Development Outsourcing

Go Beyond

  • Application Design
  • Go Walkthrough

Go Walkthrough: bytes + strings

Ben Johnson

In the previous post we covered byte streams but sometimes we need to work with bounded, in-memory byte slices instead. While working with a list of bytes seems simple enough, there are a lot of edge cases and common operations that make using the bytes package worthwhile. We’re also going to lump in the strings package in this post since its API is nearly identical although for use with strings.

This post is part of a series of walkthroughs to help you understand the Go standard library better. While generated documentation provides a wealth of information, it can be difficult to understand packages in a real world context. This series aims to provide context of how standard library packages are used in every day applications. If you have questions or comments you can reach me at @benbjohnson on Twitter.

A brief aside on bytes vs strings

Rob Pike has an excellent, thorough post on strings, bytes, runes, and characters but for the sake of this post I’d like to provide more concise definitions from an application developer standpoint.

Byte slices represent a mutable, resizable, contiguous list of bytes. That’s a mouthful so let’s understand what that means.

Given a slice of bytes:

It’s mutable so you can update elements:

It’s resizable so you can shrink it or grow it:

And it’s contiguous so each byte exists one after another in memory:

Strings, on the other hand, represent an immutable , fixed-size , contiguous list of bytes. That means that you can’t update a string — you can only create new ones. This is important from a performance standpoint. In high performance code, constantly creating new strings adds a lot of load on the garbage collector.

From an application development perspective, strings tend to be easier to use when working with UTF-8 data, they can be used as map keys whereas byte slices cannot, and most APIs use strings for arguments containing character data. On the other hand, byte slices work well when you’re dealing with raw bytes such as processing byte streams. They are also good to use when you need to avoid allocations and can reuse them.

Adapting strings & slices for streams

One of the most important features of the bytes and strings packages is that it provides a way to interface in-memory byte slices and strings as io. Reader and io. Writers .

In-memory readers

Two of the most underused tools in the Go standard library are the bytes. NewReader and strings. NewReader functions:

These functions return an io. Reader implementation that wraps around your in-memory byte slice or string. But these aren’t just readers — they implement all the read-related interfaces in io including io. ReaderAt , io. WriterTo , io. ByteReader , io. ByteScanner , io. RuneReader , io. RuneScanner , & io. Seeker .

I frequently see code where byte slices or strings are written to a bytes. Buffer and then the buffer is used as a reader:

However, this approach incurs heap allocations which will be slow and use additional memory. A better option is to use the strings. Reader :

This approach also works when you have multiple strings or byte slices by using the io.MultiReader:

In-memory writer

The bytes package also includes an in-memory implementation of io. Writer called Buffer . It implements nearly all the io interfaces except io. Closer & io. Seeker . There’s also a helper method called WriteString () for writing a string to the end of the buffer.

I use Buffer extensively in unit tests for capturing log output from services. You can pass it as an argument to log. New () and then verify output later:

However, in production code, I rarely use Buffer . Despite its name, I don’t use it to buffer reads and writes since there’s a package called bufio specifically for that purpose.

Package organization

At first glance the bytes and strings packages appear large but they are really just a collection of simple helper functions. We can group them into a handful of categories:

Comparison functions

Inspection functions.

  • Prefix/suffix functions

Replacement functions

Splitting & joining functions.

Once we understand how the functions group together, the large API seems much more approachable.

When you have two byte slices or strings you may need to ask one of two questions. First, are these two objects equal? Second, which one comes before the other when sorted?

The Equal () function answers our first question:

This function only exists in the bytes package because strings can be compared with the == operator.

Although checking for equality seems easy, one common mistake is to use strings. ToUpper () to perform case-insensitive equality checks:

This is flawed because it requires 2 allocations of new strings. A better approach is to use EqualFold ():

The term “Fold” refers to Unicode case-folding . It encompasses regular uppercase & lowercase rules for A-Z as well as rules for other languages such as converting φ to ϕ.

To determine the sort order for two byte slices or strings, we’ll use Compare ():

This function returns -1 if a is less than b , 1 if a is greater than b , and 0 if a and b are equal. This function exists in the strings package only for symmetry with the bytes package. Russ Cox even calls out in the function’s comments that “ basically no one should use strings.Compare. ” Instead, use the built-in < and > operators.

“Basically no one should use strings.Compare”, Russ Cox

Typically you’ll want to know if a byte slice is less than another byte slice for the purpose of sorting. The sort. Interface requires this for its Less() function. To convert from the ternary return value of Compare () to the boolean required by Less(), we simply check for equality with -1:

The bytes & strings packages provide several ways to find data within your byte slices and strings.

If you are validating input from a user, it’s important to verify that certain bytes exist (or don’t exist). You can use the Contains () function to check for existence of one or more subslices or substrings:

For example, you may not allow input with certain off-color words:

If you need to obtain the exact number of times a subslice or substring was used, you can use Count ():

Another use for Count () is to return the number of runes in a string. By passing in an empty slice or blank string as the sep argument, Count () will return the number of runes + 1. This is different from len () which will return the number of bytes. The distinction is important when dealing with multi-byte Unicode characters:

The first line above may seem odd because there are 5 runes but remember that Count () returns the rune count plus one.

Asserting contents is important but sometimes you’ll need to find the exact position of a subslice or substring. You can do this using the index functions:

There are multiple index functions for different use cases. Index () finds a multi-byte subslice. IndexByte () finds a single byte within a slice. IndexRune () finds a unicode code-point within a UTF-8 interpreted byte slice. IndexAny () works like IndexRune () but searches for multiple code-points at the same time. Finally, IndexFunc () allows you to pass in a custom function to evaluate each rune in your byte slice until a match.

There’s also a matching set of functions for searching for the first instance of the end of a byte slice or string:

I don’t use the index functions much because I find that I typically need to build something more complex such as a parser.

Prefixing, suffixing, & trimming

Working with content at the beginning and end of a byte slice or string is a special case of inspection but it’s a important enough to warrant its own section.

Checking for prefixes & suffixes

Prefixes come up a lot in programming. For example, HTTP paths are typically grouped by functionality with common prefixes. Another example is special characters at the beginning of a string such as “@” for mentioning a user.

The HasPrefix () and HasSuffix () functions allow you to check for these situations:

These functions may seem too simple to bother with but one common mistake I see is when developers forget to check for zero length values:

This code looks simple enough but if str is blank then the program will panic. The HasPrefix () function includes this validation for you:

The term “trimming” in the bytes and strings packages refers to removing bytes or runes from the beginning and/or end of a byte slice or string. The most generic function for this is Trim ():

This will remove any runes in cutset from the beginning and end of your string. You can also trim from just the beginning or just the end of your string using TrimLeft () and TrimRight (), respectively.

But generic trimming isn’t very common. Most of the time you want to trim white space characters and you can use TrimSpace () for this:

You might think that trimming with a “ \n\t” cutset is enough but TrimSpace () will trim all Unicode defined white space. This includes not only the space, newline, and tab characters but also more unusual white space characters such as thin space or hair space .

TrimSpace () is actually just a thin wrapper around TrimFunc () which is a function for evaluating leading and trailing runes for trimming:

This makes it simple to create your own whitespace trimmer for only trailing characters:

Finally, if you want to trim exact prefixes or suffixes instead of character sets, there are the TrimPrefix () and TrimSuffix () functions:

These can go hand in hand with the HasPrefix () and HasSuffix () functions if you want to replace a prefix or suffix. For example, I use this to implement Bash-style home directory completion for paths my config files:

Basic replacement

Swapping out subslices or substrings is sometimes necessary. For the most simple cases, the Replace () function is all you need:

It swaps out any instance of old with new in your string. You can set n to a non-negative number to limit the number of replacements. This function is good if you have a simple placeholder in a user defined template. For example, you want to let users specify “$NOW” and have it replaced with the current time:

If you have multiple mappings then you’ll need to use strings. Replacer . This works by specifying old/new pairs to strings. NewReplacer ():

Case replacement

You may assume that casing is simple — upper & lower case — but Go works with Unicode and Unicode is never that simple. There are 3 types of casing: upper, lower, and title case.

Uppercase and lowercase are straight foward for most languages and you can use the ToUpper () and ToLower () functions:

However, some languages have different rules for casing. Turkish, for example, uppercases its i as İ . For these special case languages, there are special versions of these functions:

Next we have title case and the ToTitle () function:

You may be surprised, however, when you use ToTitle () and all your characters are uppercased:

That’s because in Unicode, title case is a specific type of casing and not a way to capitalize the first character in each word. For the most part, title case and upper case are the same but there are a few code points which have differences. For example, the lj code point (yes, that’s one code point) is uppercased as LJ but title cased as Lj.

What you’re probably looking for is the Title () function:

This outputs the expected result:

Mapping runes

One other function for replacing data in a bytes slice or string is Map ():

This function lets you pass in a function to evaluate every rune and replace it. Admittedly, I didn’t even know this function existed until I started writing this post so I can’t give any personal anecdote.

Many times we have delimited strings that we need to break apart. For example, paths in Unix are joined with colons and the CSV file format is essentially just fields of data delimited by commas.

Substring splitting

For simple subslice or substring splitting, we have the Split() functions:

These break up byte slices or strings by a delimiter and return the subslices or substrings. The “After” functions include the delimiter at the end of the substrings. The “N” functions limit the number of splits that can occur:

Splitting data is a very common operation, however, it’s typically done in the context of a file format such as CSV or in the context of path splitting. For these operations, I use the encoding/csv or path packages instead.

Categorical splitting

Sometimes you want to specify delimiters as a set of runes instead of a series of runes. The best example of this is breaking apart words by variable-length whitespace. Simply calling Split () using a space delimiter will give you empty substrings if you have multiple contiguous spaces. Instead you can use the Fields() function:

This will consider consecutive whitespace characters a single delimiter:

The Fields() function is just a simple wrapper around FieldsFunc() which lets you pass a function to evaluate each rune as a delimiter:

Instead of breaking apart delimited data, we can join it together using the Join() function:

One common mistake I‘ve seen is when developers try to implement join by hand. It looks something like:

The flaw in this code is that you are creating a massive number of allocations. Because strings are immutable, each iteration is generating a new string for each append. The strings. Join () function, on the other hand, uses a byte slice buffer to build upon and converts it back to a string when it returns. This minimizes heap allocations.

Miscellaneous functions

There’s two functions I couldn’t find a category for so they’re lumped in here at the bottom. First, the Repeat () function allows you generate a repeated byte slice or string. Honestly, the only time I can remember using this is to make a line to separate content in the terminal:

The other function is Runes () which returns a slice of all runes in a UTF-8 interpreted byte slice or string. I‘ve never needed to use this since the for loop over a string does the same thing but without the allocations.

Byte slices and strings are fundamental primitives in Go. They are the in-memory representations for series of bytes and runes. The bytes and strings packages provide a ton of useful helper functions as well as adapters to the io.Reader and io.Writer interfaces.

It’s easy to overlook many of the useful tools in these packages because of the API’s size but I hope this post has helped you to understand everything these packages have to offer.

Ben Johnson

Ben Johnson

Freelance Go developer, author of BoltDB

You might also like

Go walkthrough: fmt.

In the last post we looked at fast, primitive encoding using strconv [https://golang.org/pkg/strconv/] but in this post we’ll take a higher level approach by using templates with the fmt [https://golang.org/pkg/fmt/] package. The fmt [https://golang.org/pkg/fmt/] package builds on

Go Walkthrough: strconv

Formatting & parsing primitive values in Go is a common task. You probably first dipped your toes into the fmt [https://golang.org/pkg/fmt/] package when you started Go, however, there’s a less commonly used package for basic formatting that’s more efficient and preserves compiler type checking.

Featured Posts

Standard package layout.

Standard Package Layout

GO Bytes to String Conversion Best Practices [5 Methods]

May 8, 2024

Byte slices ( []byte ) and strings are two of the basic data structures in Go programming language used to represent both text and binary data. These can be sequences of characters, but differ in a number of aspects such as mutability, usage and internal representation. In Go, a string is an immutable sequence of bytes with a definite length which makes it safe to share these objects among multiple goroutines concurrently. Conversely, a slice of bytes is capable of being modified and refers to an array containing those bytes. Because of this, an operation to convert or bridge between the two types has become commonplace for input-output tasks, file handling or network communications.

Different Methods for GO Bytes to String conversion

  • Direct conversion using type casting.
  • Use the fmt.Sprintf function for string formatting.
  • Utilizing the strings.Builder for efficient concatenation in loops.
  • Applying the strconv package for conversion with numeric interpretation.
  • The bytes.Buffer helps you convert and manipulate byte slices.
  • Reads bytes from files into strings straight from io/ioutil packages (note that ioutil has been deprecated since Go 1.16, and similar functionality is now available in os and io ).
  • For go versions before 1.16, use io/ioutil package’s ReadAll function combined with a reader interface then cast.
  • Using os package functions read into a byte slice from files or other sources of input before converting

1. Direct conversion using type casting

One of the most basic and simple methods in which you can convert a byte slice ( []byte ) to a string in Go is direct conversion using type casting. What this method does is use Go's type conversion syntax to transfer data from one type to another, which will be on our end []byte to string. If you aren't aware, strings in Go are a read-only slice of bytes. That being known, there's no need for complex processes or external library functions when converting from []byte aka the byte slice that we're given. All we need to do is instruct the compiler directly by treating it as a string. This operation isn't only very efficient because it doesn't copy any bytes but instead creates a header that points to the same underlying byte array.

Examples of Direct Type Conversion :

Basic Conversion :

Here, we've got a straightforward example where a byte slice b representing the word "Hello" is converted directly to a string s .

Numeric Byte Values :

This example uses the ASCII values for the characters. When converted, it still produces the word "Hello" as a string.

Non-ASCII Characters :

Go's string and byte slice types support UTF-8 encoding natively. Here, the byte slice represents the Chinese phrase "你好" (Hello).

Empty Byte Slice :

Even when dealing with empty byte slices, direct conversion results in an empty string without any issues.

2. Using fmt.Sprintf

The Go standard library has a versatile format string function , fmt.Sprintf . It not only converts different data types into string but also formats them in accordance with specific patterns. In terms of converting byte slices ( []byte ) to strings, fmt.Sprintf offers an option for doing so along with additional formatting options if required. On the other hand, while fmt.Sprintf is not the most direct way to convert bytes to a string because it incurs the overhead of handling a format string, it proves useful when you want to either include that byte slice within a larger string or get more out of the byte data in question by giving it particular forms of formatting.

If you want to convert a byte slice into a string using fmt.Sprintf then you can apply %s format verb which implies that argument should be formatted as a string. Here are some examples of Converting Byte Slices to Strings using fmt.Sprintf :

In this example, fmt.Sprintf is employed to convert the byte slice b to a string. The format verb %s is used to represent the byte slice as a string.

With Additional Formatting :

Here, we not only perform the go bytes to string conversion but also embed the resulting string within a larger formatted string.

Conversion Alongside Other Data Types :

This example showcases the power of fmt.Sprintf to handle multiple data types concurrently , integrating the byte-to-string conversion seamlessly within a broader context.

Hexadecimal Representation :

Using the %x verb, we can represent the byte slice in its hexadecimal form, illustrating fmt.Sprintf 's flexibility beyond mere string representation.

3. Using bytes.Buffer Type

The bytes.Buffer type within the Go library is a variable-sized, very perplexing buffer of bytes with read and write methods. This type is part of the bytes package , and it is commonly used for reading from and writing to buffers. The bytes.Buffer in Go is used for efficient manipulation and conversion of byte slices.

Examples of Conversion Using the bytes.Buffer Type :

Here, we initiate a Buffer , write our byte slice b to it, and then effortlessly convert it into a string using the String() method.

Concatenating Multiple Byte Slices :

With Buffer , concatenating multiple byte slices becomes a breeze. This approach is not only intuitive but also efficient, especially when dealing with multiple byte slices.

Applying Transformations Before Conversion :

One of the beauties of Buffer is its seamless integration with other packages, allowing for transformations, like converting to lowercase, post-conversion.

Efficient Handling of Large Byte Slices :

Buffer type is a memory efficient way to convert a bunch of bytes into a string, it just works by minimizing allocations during operations.

Honestly direct conversion and fmt.Sprintf can do the job for basic use cases. But there are scenarios where the Buffer approach can be advantageous:

  • Large Data Handling : If you're working with vast amounts of data, the Buffer type will make sure your memory usage stays efficient
  • Multiple Concatenations:  Let's say you need to add or combine multiple byte slices, Buffer performs significantly better than simple slice appending.
  • Flexibility : It plays well with other Go packages like strings, allowing you to execute many different operations beyond just converting things.

4. Using unsafe

The unsafe package is a unique one within the vast realm of packages that Go offers. While other packages focus on more general, mundane tasks, unsafe says “screw that” and shows you Go’s memory representation and its type system. But if its name is asking for caution, it’s probably for good reason. Of the many things you can do with this package, one that stands out is how it handles byte to string conversion. But as versatile as it may be, its risks are equally noteworthy.

General Summary: The Go package called unsafe is a double-edged sword. Although it gives developers direct access to manipulating memory and converting types at a low level, it ditches the safety mechanism in place by default in Go's type system. This means applications built using this package might run into unexpected behaviors or vulnerabilities if misused.

Examples of Conversion Using the unsafe Package :

Basic Unsafe Conversion :

Here, we directly manipulate memory pointers to cast a byte slice to a string. It's quick and allocates no additional memory, but it's, well, unsafe.

Pitfalls of Using Unsafe : Suppose you modify the original byte slice after converting it using unsafe :

In this example, we saw just how closely tied the byte slice and string are when converted with unsafe . Changing one will affect the other — something you wouldn’t expect at first glance and could pose dangers in some situations.

Possible Pitfalls : You don’t need me to tell you that bypassing type safety opens up a world of opportunities for optimizations. However, these opportunities come with risks:

  • Memory Safety : Go’s robust type system goes a long way in preventing common programming mistakes. Going around it leaves open entirely new ones related to memory management.
  • Maintenance Trouble : Code that uses this package can become harder to maintain and evolve as changes are made to the language or compiler itself.
  • Data Integrity : If there’s anything these examples have shown us, it’s that data integrity can be compromised when sharing references between unsafe variables that stakeholders may modify incorrectly.

5. Using strings.Builder Method

The strings.Builder type within Go's standard library was designed for efficiently building strings through data appending, including but not limited to: bytes or strings themselves. Strings.Builder provides a way for developers like yourself to construct strings more efficiently than with concatenation. In scenarios where multiple appends are performed, it minimizes memory copying and allocation which makes it faster than other methods.

Although strings.Builder has been crafted primarily for string construction rather than converting byte slices; That doesn’t mean you can’t use it for that purpose — especially if many appends will be performed before doing so

Examples of Conversion Using the strings.Builder Method :

Basic Conversion using strings.Builder :

Here, we initiate a strings.Builder , write our byte slice to it, and then convert it to a string.

Appending Multiple Byte Slices :

Using strings.Builder makes adding multiple byte slices together before completing the string switch so much easier.

Comparing strings.Builder with bytes.Buffer : Strings.Builder and bytes.Buffer may seem to do similar things but they have their distinctions:

  • Purpose Specificity :  bytes.Buffer is considered a more general-purpose buffer because it holds both bytes and strings. On the other hand, string builders only work with string building, this means that code using them is much clearer in its intent.
  • Performance : For tasks that only deal with building strings, strings.Builder might be faster due to it being stripped of additional functionality provided by bytes.Buffer .
  • Methods Availability:   bytes.Buffer has a bigger selection of methods for more flexible byte-based operations while string builders have minimalistic APIs.

In the course of learning how to convert byte slices to strings in Go, we have seen that several methods can be used with their own unique characteristics and appropriate applications. As earlier stated, a variety of tools are out there for Go programmers:

  • Direct Type Conversion : A simple and effective technique which is suitable for almost all common situations.
  • Using fmt.Sprintf : This approach is flexible giving more than just conversion and especially if formatting is important.
  • The bytes.Buffer Type : It’s perfect when manipulating or concatenating byte slices needs to be done efficiently.
  • The Risky unsafe Package : The best specialist tool ever known which one should not touch unless there is a compelling performance need, even then with great care.
  • The strings.Builder Method : This method is specialized and optimized for string building hence it finds use in applications where string manipulation dominates.

All in all, the “go bytes to string” problem reflects the richness of Go as a language. However, every single method has its peculiarities such that it might be judged pragmatically given certain aspects including speed, safety and readability.

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to [email protected]

Thank You for your support!!

Leave a Comment Cancel reply

Save my name and email in this browser for the next time I comment.

Notify me via e-mail if anyone answers my comment.

golang byte assignment

We try to offer easy-to-follow guides and tips on various topics such as Linux, Cloud Computing, Programming Languages, Ethical Hacking and much more.

Recent Comments

Popular posts, 7 tools to detect memory leaks with examples, 100+ linux commands cheat sheet & examples, tutorial: beginners guide on linux memory management, top 15 tools to monitor disk io performance with examples, overview on different disk types and disk interface types, 6 ssh authentication methods to secure connection (sshd_config), how to check security updates list & perform linux patch management rhel 6/7/8, 8 ways to prevent brute force ssh attacks in linux (centos/rhel 7).

Privacy Policy

HTML Sitemap

IncludeHelp_logo

  • Data Structure
  • Coding Problems
  • C Interview Programs
  • C++ Aptitude
  • Java Aptitude
  • C# Aptitude
  • PHP Aptitude
  • Linux Aptitude
  • DBMS Aptitude
  • Networking Aptitude
  • AI Aptitude
  • MIS Executive
  • Web Technologie MCQs
  • CS Subjects MCQs
  • Databases MCQs
  • Programming MCQs
  • Testing Software MCQs
  • Digital Mktg Subjects MCQs
  • Cloud Computing S/W MCQs
  • Engineering Subjects MCQs
  • Commerce MCQs
  • More MCQs...
  • Machine Learning/AI
  • Operating System
  • Computer Network
  • Software Engineering
  • Discrete Mathematics
  • Digital Electronics
  • Data Mining
  • Embedded Systems
  • Cryptography
  • CS Fundamental
  • More Tutorials...
  • Tech Articles
  • Code Examples
  • Programmer's Calculator
  • XML Sitemap Generator
  • Tools & Generators

IncludeHelp

Golang Tutorial

  • Golang - Home
  • Golang - Keywords
  • Golang - Data Types
  • Golang - Variables
  • Golang - Constants
  • Golang - Program Structure
  • Golang - Comments
  • Golang - Naming a variable
  • Golang - Shorthand for Defining Multiple Variables/Constants
  • Golang - Find Type of Variable
  • Golang - Binary Literals
  • Golang - Octal Literals
  • Golang - Hexadecimal Literals
  • Golang - Type Casting or Type Conversion
  • Golang – Operators
  • Golang - Arithmetic Operators
  • Golang - Relational Operators
  • Golang - Logical Operators
  • Golang - Bitwise Operators
  • Golang - Assignment Operators
  • Golang - Miscellaneous Operators
  • Golang - if statement
  • Golang - if-else statement
  • Golang - if-else-if ladder statement
  • Golang - nested if statement
  • Golang - switch statement
  • Golang - select statement
  • Golang - Loops
  • Golang - Functions
  • Golang - Strings

Golang Reference

  • Go - builtin Package
  • Go - bytes Package
  • Go - fmt Package
  • Go - math Package
  • Go - os Package
  • Go - sort Package
  • Go - strconv Package
  • Go - strings Package
  • Go - unicode Package
  • Golang Programs
  • Golang Programs - Home
  • Golang - Basic Programs
  • Golang - Switch Statement Programs
  • Golang - goto Statement Programs
  • Golang - Looping Programs
  • Golang - Array Programs
  • Golang - String Programs
  • Golang - Structure Programs
  • Golang - User-defined Function Programs
  • Golang - Variadic Function Programs
  • Golang - Recursion Programs
  • Golang - Pointer Programs
  • Golang - Conversion Programs
  • Golang - Slices Programs
  • Golang - Date & Time Programs
  • Golang - Timers & Tickers Programs
  • Golang - Goroutines Programs
  • Golang - Reflection Programs
  • Golang - Maps Programs
  • Golang - Range Programs
  • Golang - Channels Programs
  • Golang - File Handling Programs
  • Golang - Buffered Input-Output Programs
  • Golang - Command-line Arguments Programs
  • Golang - Regular Expressions Programs
  • Golang - JSON Programs
  • Golang - os Package Programs
  • Golang - strconv Package Programs
  • Golang - log Package Programs
  • Golang - math/rand Package Programs
  • Golang - math/bits Package Programs
  • Golang - sync/atomic Package Programs
  • Golang - path/filepath Package Programs
  • Golang - syscall Package Programs
  • Golang - Signals Programs
  • Golang - Shell Script Programs

Golang Practice

  • Golang Interview Questions
  • Golang Find Output Programs
  • Golang Aptitude Questions

Golang Miscellaneous

  • Golang - Print Boolean Value
  • Golang - Print Double-quoted String
  • Golang - Convert From Int to Binary
  • Golang - Convert From Int to Octal
  • Golang - Convert From Int to Hex
  • Golang - Check if Structure is Empty
  • Golang - Check if Key Exists in Map
  • Golang - Return an Error
  • Golang - new() & make() Functions

Advertisement

Home » Golang » Golang FAQ

How to assign string to bytes array in Golang?

Go language | Learn, how to assign a string to the bytes array and how to append a string at the end of the bytes array? Submitted by IncludeHelp , on October 19, 2021

The simple, easy, and safest way is to assign a string to bytes array is,

Consider the below example,

Golang FAQ »

Comments and Discussions!

Load comments ↻

  • Marketing MCQs
  • Blockchain MCQs
  • Artificial Intelligence MCQs
  • Data Analytics & Visualization MCQs
  • Python MCQs
  • C++ Programs
  • Python Programs
  • Java Programs
  • D.S. Programs
  • C# Programs
  • JavaScript Examples
  • jQuery Examples
  • CSS Examples
  • C++ Tutorial
  • Python Tutorial
  • ML/AI Tutorial
  • MIS Tutorial
  • Software Engineering Tutorial
  • Scala Tutorial
  • Privacy policy
  • Certificates
  • Content Writers of the Month

Copyright © 2024 www.includehelp.com. All rights reserved.

string and []byte conversion problem in golang

Table of contents.

Let’s look at the problematic code, similar string and []byte conversion code is very common on the web.

StringToSliceByte(s string) []byte { l := len(s) return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ Data: (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data, Len: l, Cap: l, })) }

The reason why people don’t want to convert a string to a []byte directly via []byte(string) is because that would involve a memory copy, whereas a type conversion via unsafe.Pointer does not involve a memory copy, thus improving performance.

Is there a problem with this code or not? Actually, when I copied the code into vscode, I was prompted with

SliceHeader is the runtime representation of a slice. It cannot be used safely or portably and its representation may change in a later release. Moreover, the Data field is not sufficient to guarantee the data it references will not be garbage collected, so programs must keep a separate, correctly typed pointer to the underlying data.

Firstly, reflect.SliceHeader is used as a runtime representation of a slice, which may change later, and there is a risk of using it directly; secondly, there is no guarantee that the data it points to will not be rubbish collected by GC.

The first problem is fine, but the latter, the GC problem, is a big one! Why there is a GC problem, let’s look at the definitions of reflect.SliceHeader and reflect.

SliceHeader struct { Data uintptr Len int Cap int } type StringHeader struct { Data uintptr Len int }

As you can see above, Data is of type uintptr, and although it has a ptr suffix, it is still essentially an integer, not a pointer, which means that it does not hold the data it points to, so the data may be reclaimed by GC.

Now that we know the cause and effect, let’s construct a piece of code that demonstrates that there is a GC problem.

main import ( "fmt" "reflect" "runtime" "unsafe" ) func main() { fmt.Printf("%s\n", test()) } func test() []byte { defer runtime.GC() x := make([]byte, 5) x[0] = 'h' x[1] = 'e' x[2] = 'l' x[3] = 'l' x[4] = 'o' return StringToSliceByte(string(x)) } func StringToSliceByte(s string) []byte { l := len(s) return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ Data: (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data, Len: l, Cap: l, })) }

Note: Dynamic strings are used because static strings are stored in the TEXT area and will not be reclaimed by the GC.

When we run the above code, it does not output hello, but gibberish, because the corresponding data has already been reclaimed by the GC, if we remove runtime.GC() and run it again, the output will probably be normal again.

This shows that because Data is of type uintptr, any assignment to it is unsafe. This should have been the end of the matter, but the unsafe.Pointer documentation happens to have an example of a direct assignment to Data: Conversion of a reflect.SliceHeader or reflect.Pointer.

s string hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) hdr.Data = uintptr(unsafe.Pointer(p)) hdr.Len = n

Whether the documentation is wrong or our inference is wrong, continue to read the documentation which states.

the reflect data structures SliceHeader and StringHeader declare the field Data as a uintptr to keep callers from changing the result to an arbitrary type without first importing “unsafe”. However, this means that SliceHeader and StringHeader are only valid when interpreting the content of an actual slice or string value.

That is, the SliceHeader or StringHeader is only valid if it operates on a slice or string that actually exists, and recall that the original code did not comply with unsafe.Pointer because there was no actual slice when it operated on reflect. Pointer ( golang-nuts ), adjust it as required.

Running it through the test code again, the output is now normal. However, some people may ask, didn’t we say before that uintptr is not a pointer and can’t prevent data from being reclaimed by GC, but why does GC have no effect? In fact, this is because the compiler did special handling on the *reflect.{Slice,String}Header.

If you want to verify that there is special handling, you can use a custom type reversal to verify that.

StringHeader struct { Data uintptr Len int } type SliceHeader struct { Data uintptr Len int Cap int } func StringToSliceByte(s string) []byte { var b []byte l := len(s) p := (*SliceHeader)(unsafe.Pointer(&b)) p.Data = (*StringHeader)(unsafe.Pointer(&s)).Data p.Len = l p.Cap = l return b }

You’ll notice that if you don’t use the type in reflect, then the output doesn’t work again. This backfires and verifies that the compiler is indeed doing something special with *reflect.{Slice,String}Header .

Now that we’ve basically figured out the pitfalls of string and []byte conversions, here’s a look at how to write accurate conversion code, although the compiler plays a few tricks with it, but we shouldn’t rely on these underhanded operations.

Since uintptr is not a pointer, let’s use unsafe.Pointer instead, so that the data is not reclaimed by GC.

StringHeader struct { Data unsafe.Pointer Len int } type SliceHeader struct { Data unsafe.Pointer Len int Cap int } func StringToSliceByte(s string) []byte { var b []byte l := len(s) p := (*SliceHeader)(unsafe.Pointer(&b)) p.Data = (*StringHeader)(unsafe.Pointer(&s)).Data p.Len = l p.Cap = l return b }

The above code is slightly bloated, for a simpler way of writing it see gin or fasthttp for implementations.

func StringToBytes(s string) []byte { return *(*[]byte)(unsafe.Pointer( &struct { string Cap int }{s, len(s)}, )) } func BytesToString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // fasthttp func s2b(s string) (b []byte) { /* #nosec G103 */ bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) /* #nosec G103 */ sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) bh.Data = sh.Data bh.Cap = sh.Len bh.Len = sh.Len return b } func b2s(b []byte) string { /* #nosec G103 */ return *(*string)(unsafe.Pointer(&b)) }

At this point, we have solved the problem of converting string and []byte perfectly.

Why i can not assign int to byte

why it is impossible to do the following

rot13[i] = val + num

but it is ok to do that

rot13[i] = val + 22

if I am not mistaken 22 and num both are ints so i do not understand why this happen

An int is a different type than a byte and Go does not do implicit conversions. You can do it yourself by saying byte(num) , knowing that you will of course truncate the value as int is larger than byte.

The constant 22 is not an int - it’s an untyped constant. These can take on any numeric type depending on the context. In this case it will become a byte constant since it’s used in a byte context.

A numeric integer constant will default to the int type if there is no context ( var foo = 22 // foo is now int ), which is what you’re thinking of.

Here’s a deeper look at constants: https://blog.golang.org/constants

:slight_smile:

Calmh, Sunnykarira, guys thank you very much, you are really helping me to understand golang

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications You must be signed in to change notification settings

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: provide no-copy conversion from []byte to string #25484

@tliron

tliron commented May 22, 2018

If you read bytes from an , but need them as a , then you're going to have to convert. And that will cost you memory as data is copied between quite different variables.

Annoyed by this waste, some of us has been doing things like this:

Of course, proper use requires you to never change the original byte array, but that's a reasonable contract in many cases.

First, I would like to know if there are any repercussions to this usage. I'm always nervous about using , but in this case it seems to adhere to the spec, and also I can't foresee any problems with garbage collection. But maybe I'm missing something important. I've been using this a lot and have not seen any issues.

Second, assuming this code is A-OK, then why not provide something like this in the standard library? (Probably in the package.) It could allow for significant memory savings for programs that read a lot of text.

  • 👍 4 reactions
  • 👎 1 reaction

@randall77

randall77 commented May 22, 2018

That's not quite the right way to do it. See the description at the end of package 's description. (TL;DR don't declare variables of type or , use variables of type and instead.) But in general, if you want to do this in your code, go for it. is a proposal to make this a bit nicer/safer.

We don't want to provide this functionality (unsafe-converting a to ) in the standard library because it lets people create mutable strings. Lots of packages assume strings are immutable, and may behave badly if the strings are mutable. For instance, maps with mutable string keys will behave badly. We'd rather not encourage those kinds of bugs, even if you can do it yourself.

If and when we do , adding copy-free to would be an easy additional operation. But maybe we just keep letting people do that themselves.

  • 👍 2 reactions

Sorry, something went wrong.

@bcmills

bcmills commented May 22, 2018

As notes, this would have to live in the package (because it is unsafe in general). As such, closing as a dup of .

@bcmills

I understand the concern, but this just seems to be such a common use case with very obvious gains. I understand that Go is focused more on engineering practicality than language correctness.

Since we already have an package, how about adding this function there? Is that the point of ? By having it in users should be clear as to what they're getting into ( immutable strings).

Here's my new way to do it by avoiding an instance of . Does this look right?

It's actually subtly tricky to ensure that the byte slice doesn't get GC'ed. I took into account the comment to do it all in one line.

I think this is safer.

That way you're never allocating an instance of .

tliron commented May 22, 2018 • edited Loading

Thanks, but that doesn't compile in go1.10.2. Is it even possible to do on implicit returns? This does work:

Ah, I forgot a final "return".
Yes, you can take the address of named return values.
Your version is fine as well.

With the missing return, it seems to work:

FWIW, you can also write it without referring to :

Thanks! Here's my final version with .

See, the subtleties of getting this right are exactly why this should be a std func.

@zigo101

zigo101 commented May 23, 2018 • edited Loading

The function above is not safe under current unsafe rules.
It needs a line:

BytesToString(bytes []byte) (s string) { slice := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) str := (*reflect.StringHeader)(unsafe.Pointer(&s)) str.Data = slice.Data str.Len = slice.Len runtime.KeepAlive(&bytes) // this line is essential. return s }

tliron commented May 23, 2018

Thanks very much, go101.

For a closed issue this one is getting a lot of input. ;) Again, I imagine very, very few people out there are getting this critical code right. See and for wrong ways of doing this.

Folk, I think this should be in Go std lib, if only to save people from themselves. Many people will try to do this and mess up.

bcmills commented May 23, 2018

Unless I have missed something, the version without ( ) does not require a . Before the pointer is written it is reachable via an , and after it is written it is reachable via the variable.

If is accepted, then it will be much easier to get right: that proposal uses instead of for the field, which means that the garbage collector will correctly trace slices that are only reachable via a or .

The only reason this is tricky today is because the headers are in instead of , and as such cannot use the correct type for the field (see ).


yes, the way used by strings.Builder

ByteSlice2String(bs []byte) string { return *(*string)(unsafe.Pointer(&bs)) }

is a more efficient way.

tliron commented May 24, 2018

Thanks, go101. For reference, .

@semihalev

No branches or pull requests

@tliron

Posts View All

Events view all, professionals view all, companies view all, log in to view notifications..

Log in to access your notifications and stay updated. If you’re not a member yet, Sign Up to get started!

expo event

Elena R Elena R

Elena is an expert in technical analysis and risk management in cryptocurrency market. She has 10+year experience in writing - accordingly she is avid journalists with a passion towards researching new insights coming into crypto erena.

author twitter

  • Sep 18, 2024 11:48 UTC
  • 11 minutes read

Step-by-Step Guide to Building a Blockchain with Go (Golang)

golang byte assignment

  • Introduction 

Blockchain has fundamentally transformed how we view data and security. At its core, blockchain is a distributed ledger that records transactions across multiple nodes, making it nearly impossible to alter these records once they are confirmed. This groundbreaking innovation has revolutionized the finance sector, giving rise to the cryptocurrency market. 

But blockchain’s influence doesn’t stop there—it’s reshaping industries like healthcare, supply chain management, and beyond.

  • Go (Golang): The Perfect Match for Blockchain Development

Go, also known as Golang, is a programming language developed by Google, celebrated for its efficiency and scalability in software development. As a statically typed, compiled language, Go translates code directly into machine language, resulting in faster execution—something blockchain networks critically need.

Blockchain systems demand speed and high throughput, which is where Go excels.

One of Go’s standout features is its ability to support concurrency. This means Go can handle multiple operations simultaneously, maximizing system utilization. In blockchain, where multiple blocks and transactions occur at once, Go’s concurrency model manages these tasks efficiently without complicating multi-thread management.

Library for Blockchain Needs

Go comes with a comprehensive standard library that provides essential packages for networking, cryptography , and data handling—key functionalities for any blockchain system. Additionally, Go’s simplicity and readability reduce the learning curve, making it easier for developers to grasp the language and its syntax quickly.

Strong Community Support

With a large, active community and growing industry support, resolving any issues that arise during blockchain development becomes easier. Go offers a robust foundation for developers looking to build scalable, high-performance blockchain solutions.

  • A Hands-On Guide for Blockchain Development with Go

This article is tailored for beginners diving into the worlds of Go and blockchain. You’ll learn everything from setting up your environment to configuring prerequisites, and compiling, and testing your own blockchain applications. So, are you ready to explore blockchain with Go? Let’s get started! 

  • Understanding Blockchain Concepts with Go

Before we dive into the syntax and functions, it’s essential to grasp the core concepts of blockchain. Understanding these fundamentals will make it easier to follow the technical steps ahead.

Blockchain Basics in Go

Blockchain has three components: Blocks, transactions, and Chains.

Blocks: A block is a primitive unit of blockchain, it permanently stores the data of transactions. Each block has its own metadata– such as the index, timestamp, hash, and actual transaction information. These blocks are chained together, forming a sequential and immutable ledger.

Transaction: Transactions are the driving force of the system. They represent all the necessary information regarding the exchange of currency, transfer of information, etc on the network. Every block contains a series of transactions that are processed and verified by the blockchain network.

Chain: Each block has a pointer to the previous block that acts as a reference and this continuous link of blocks together is called a chain of blocks, Hence Blockchain.

Core Principles of Blockchain

Decentralization: Unlike traditional databases managed by a central authority, blockchain distributes control across multiple nodes. Each node maintains a copy of the blockchain, ensuring transparency and reducing the risk of centralized corruption or failure.

Immutability: Once data is recorded on the blockchain, it cannot be altered. This is achieved by linking each block to the previous one using a cryptographic hash. Any attempt to tamper with a block alters its hash, breaking the chain and alerting the network.

Consensus Mechanism:  Consensus mechanisms are protocols that all participants use to validate transactions and the state of the ledger. Common mechanisms include Proof of Work (PoW), Proof of Stake (PoS), and Practical Byzantine Fault Tolerance (PBFT).

Ready to Build Blockchain with Go?

By now, you should have a solid grasp of blockchain fundamentals. Now comes the exciting part! In the following sections, we’ll guide you step-by-step through building your own blockchain applications using Go.

Get ready to get hands-on! Let’s dive into the practical side of blockchain development with Go.

  • Chapter 1: Setting Up the Development Environment

Before you hop on to writing code and contracts, the right development environment is necessary. This involves a couple of steps. Below is a detailed guide to get started. Get set go!!

Installing Go

  • Download and install the latest version of Go from the  official website
  • Make sure you download the system-specific version(Windows, Mac Os, Linux)
  • Set up the environment variables:

Windows: The Go installer  adds Go to your system’s PATH automatically, but you can manually add it via the System Properties > Environment Variables if needed

MacOS/Linux: export PATH=$PATH:/usr/local/go/bin (in the bash or zshrc)

Verify installation using the command: go version 

This will give you output for e.g:  go version go1.19.0 linux/amd64

Choosing an IDE

An Integrated Development Environment is the most necessary element for any kind of programming. In other words, it is another code editor. When you go to choose there are a bunch of options but the two most popular choices are VSCode and GoLand.

Visual Studio Code: VSCode – developed by Microsoft is an open-source platform, it is versatile and lightweight and is used for various programming languages. It offers powerful features like code completion, debugging, and version control.

  • Download VSCode from the official site
  • Follow the on-screen instructions and complete the installation according to your system.
  • Set up the VSCode from the extensions panel(Ctrl + Shift + X) and download all the necessary ones like– Go extension, live share, Gitlens, etc

GoLand: GoLand– developed by JetBrains, is an IDE tailored specifically for Go development. It includes powerful debugging, testing, and refactoring tools, as well as integrated database support, making it a robust choice for larger projects.

  • Download GoLand from the official JetBrains website
  • Set up and install the GoLAnd and then set up the path variables properly File →Settings →Go →GOROOT

Here you are ready to create Go blockchain projects !!

Installing Required Libraries

Use go get to install essential libraries.

  • Chapter 2: Building a Simple Blockchain with Go

Blocks are the foundation units of Blockchain. Block contains all the transaction information, unique identifiers, and links to previous blocks. In this chapter, we will explore the structure of the block in Golang in more detail.

1. Creating the Block Struct

Block is represented in the form of a data type called struct, it can be a user-defined data type. Block struct contains attributes like:

  • Index: The index is useful in denoting the position of any block in the blockchain.  
  • Timestamp: It is the time at which the block was created
  • Data: It contains any kind of information related to the transaction or the state of the block.
  • Previous hash: It is the hash of the previous block connected to the current one.
  • Hash: Unique key identifier of each block decided through cryptographic methods

In the following code snippet, we have implemented the block struct.






Implement methods to calculate the hash of the block using Go syntax:










Function calculateHash() is used to compute the hashing of the current block

2. Creating the Blockchain Struct

After you are done with defining the blockclass and its attributes you can further go and create the genesis block. The Genesis block is the first block in the blockchain that needs to be initialized and has an index of zero. After defining the genesis block you can further go on and add new blocks to your blockchain by using the addblock() method. After you add the new block calculate the hash of that block also. Here is the code:



















  • Chapter 3: Implementing Consensus Mechanisms in Go

Proof of Work

We have earlier had an overview of consensus mechanisms in this article, now let’s explore more about them in this chapter. Consensus mechanisms are crucial to secure and validate transactions and the state of the database. 

The most used Consensus Mechanism is Proof of Work . In PoW miners compete with each other in a time-bound situation to solve the difficult cryptographic puzzle. Hence, only when you find the most appropriate nonce and get it verified the new block will be added. This aggravated effort ensures that nobody can control or introduce the blocks without spending those computational efforts . 

In the first step we need to add a proof attribute to the struct:









In the second step Implement the proof of Work method to generate the proof that satisfies the difficulty level.























Update Blockchain struct to validate proof before adding new blocks. This step makes sure only valid blocks are added to the blockchain.
























  • Chapter 4: Creating a Simple Blockchain API with Go

Application programming Interface also known as API is the heart and soul of any application. API helps different software/ platforms to interact with each other. This brings in the cohesive nature and seamless integration of networks and systems external to the blockchain. APIs differentiate the front end and the backend part and simplify the interaction even more. APIs facilitate easy integration of blockchain features into existing systems

Setting Up the API Environment

Since Go is already installed and configured in your system you can go ahead and set up the API environment. Go has a standard library which is quite enough for the APIs but you can still go for Gin and Swagger to build and document your API.

Install and configure tools required for creating APIs with Go.  



Building the API

Building APIs provides a modular approach, allowing for scalable and maintainable integration of blockchain features into various systems.

Create an API to define endpoints for adding blocks and viewing the blockchain using Go.




































In the above code snippet, API Block Handlers are functions that process requests related to blockchain operations, such as adding new blocks or retrieving block data. API Endpoints are specific URLs or routes in an API that correspond to different operations or resources.

  • Chapter 5: Running and Testing the Application

The final step of any development process is Testing the application. This tells us a lot about the functionalities of the App that we have created. There are several methods of testing –Unit testing, Integrated testing, and Quality assurance testing. Testing the application before you deploy it and it is fully functional is important.

Running the Application

Compile and run the Go blockchain application.

This command compiles and executes your code. As a result, you will have requests incoming at the 8080 port as specified.

Testing with Postman

Test the API endpoints using Postman or curl.


Click Send to submit the request. You should receive a response indicating whether the block was successfully added.

  • Chapter 6: Live Example of Building a Blockchain Application with Go

Triumph! You have reached the end of the development journey. Before we conclude let’s combine everything that we have studied so far and implement it in a single step-by-step code.

Step-by-Step Execution

  • Step 1: Create the Block struct with necessary attributes using Go syntax.
  • Step 2: Implement the calculate_hash method.
  • Step 3: Define and initialize the Blockchain struct with a genesis block.
  • Step 4: Implement methods to add new blocks and retrieve the latest block using Go.
  • Step 5: Add Proof of Work functionality to the Block struct and update the Blockchain struct.
  • Step 6: Set up the API environment to handle requests using Go.
  • Step 7: Test the application by mining a new block and verifying the blockchain using Postman or curl.














































































































  • Conclusion and Future Directions

Congratulations! You’ve successfully built a functional blockchain application using Go! Through this guide, you’ve gained foundational skills, including creating a blockchain from scratch, implementing Proof of Work, and setting up a REST API to interact with your blockchain. The key takeaways from this journey include:

  • Defining and structuring blocks
  • Implementing consensus mechanisms
  • Integrating APIs for blockchain interaction

But this is just the beginning. As you continue your journey into blockchain development with Go, there are exciting areas to explore and improve.

The future of Go in decentralized application (dApp) development holds immense potential. Some advanced topics worth diving into include:

  • Exploring Advanced Consensus Mechanisms
  • Scalability Improvements
  • Interoperability
  • Real-World Applications

As you move forward, don’t hesitate to experiment, refine, and innovate. The world of blockchain is rapidly evolving, and your skills with Go will allow you to stay at the cutting edge.

Thank you for following this guide, and happy coding as you continue your blockchain development journey!

Also Check Out: How to Build Your First Blockchain with Plutus: A Step-by-Step Tutorial

Well Done! You have now completed the Lesson.

Complete the quiz and get certified all the best, follow us for inspiring posts and stories, we'd love to hear your thoughts on this article, was this writing helpful, tell us why, disclaimer and risk warning.

The information provided in this content by Coinpedia Academy is for general knowledge and educational purpose only. It is not financial, professional or legal advice, and does not endorse any specific product or service. The organization is not responsible for any losses you may experience. And, Creators own the copyright for images and videos used. If you find any of the contents published inappropriate, please feel free to inform us.

Previous Lesson Building a Blockchain Application with Simplicity

Next lesson building a blockchain application with simplicity, table of contents, select a country.

search

  • No related data found for - " ".
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

How to fix assign []byte of data in multiple assignment

How to fix this problem about datatype of this function.

Firstly, I'm new to Golang and am trying to learn it with some practice. I created a function to handle a request/GET http response.

The error warning.

I just want the function to return raw data from API response

c_anirudh's user avatar

  • The best practice is to do the whole Tour of Go tour.golang.org including all exercises. Basic stuff like how the type system works are explained in depth there. –  Volker Commented Jul 4, 2019 at 5:11

The return type of your function is of type byte , whereas the return type of ioutil.ReadAll is []byte . Those types do not match, where one is a byte and the other is a slice of bytes. Change the return type of data to []byte , assuming that is what you wanted in the first place.

mazei513's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged api http go or ask your own question .

  • The Overflow Blog
  • Looking under the hood at the tech stack that powers multimodal AI
  • Detecting errors in AI-generated code
  • Featured on Meta
  • User activation: Learnings and opportunities
  • Preventing unauthorized automated access to the network
  • Announcing the new Staging Ground Reviewer Stats Widget

Hot Network Questions

  • Why can't Voyager 1 finally "settle down" to a stable attitude, without needing "40 short puffs per day"?
  • Does General Relativity predict Mercury's orbital precession without other planets?
  • Using plural for appendix if more than one
  • Is it ok if I was wearing lip balm and my bow touched my lips by accident and then that part of the bow touched the wood on my viola?
  • Why do you even need a heatshield - why not just cool the re-entry surfaces from inside?
  • BSS138 level shifter - blocking current flow when high-side supply is not connected?
  • Solve a Differential Equation with a Free Parameter and Integrate for Plotting
  • What is the book/author about preserved heads/brains?
  • Can artistic depictions of crime (especially violence) be used as evidence?
  • how to make the latex support traditional-Chinese characters
  • Paired or unpaired t test in two samples of horses and their wound size
  • Can't redeem my denied-boarding vouchers
  • Numerical integration of ODEs: Why does higher accuracy and precision not lead to convergence?
  • How close can aircraft get to each other mid flight
  • What is this contraption off the wing of a US Navy DHC-6?
  • Has the UN ever made peace between two warring parties?
  • How can I have my paper reviewed?
  • Uppercase, lowercase – "in any case"?
  • Can Ubuntu 24.04 be compromised?
  • Can I still access the potato dimension?
  • What does "(be) able to look sad" mean?
  • Cheapest / Most efficient way for a human Wizard to not age?
  • Generic C++ Class to Associate enum Values with Strings for Translation
  • Change style of True/False everywhere

golang byte assignment

IMAGES

  1. Byte Buffer with Golang. Byte Buffer with Golang

    golang byte assignment

  2. Golang 中的 bytes 包详解(一):bytes.Buffer

    golang byte assignment

  3. GoLang Tutorial

    golang byte assignment

  4. GoLang Tutorial

    golang byte assignment

  5. Strings, Bytes and Runes

    golang byte assignment

  6. GoLang Tutorial

    golang byte assignment

VIDEO

  1. Map-Reduce Golang Assignment Test Cases Passed

  2. golang 12

  3. Solving A Subscriber's Golang Interview Assignment!

  4. #Golang : CODING SESSION

  5. P2P Protocol In Golang For My Distributed CAS

  6. Simple C++ Program for Voting: Easy Step-by-Step Guide

COMMENTS

  1. go

    The built-in copy function only copies to a slice, from a slice.; Arrays are "the underlying data", while slices are "a viewport into underlying data". Using [:] makes an array qualify as a slice.; A string does not qualify as a slice that can be copied to, but it qualifies as a slice that can be copied from (strings are immutable).; If the string is too long, copy will only copy the part of ...

  2. Go byte

    A byte in Go is an unsigned 8-bit integer. It has type uint8. A byte has a limit of 0 - 255 in numerical range. It can represent an ASCII character. Go uses rune, which has type int32, to deal with multibyte characters. The bytes package implements functions for the manipulation of byte slices. It is similar to the strings package. $ go version.

  3. Golang bytes

    Here is the syntax for declaring an empty buffer. 1. var b bytes.Buffer. To write into a Buffer we can use the write function like this. 1. 2. b.Write([]byte("a string")) fmt.Println(b.String()) // a string. The Fprintf can also be used to write into the buffer.

  4. How to convert from []byte to int in Go Programming

    binary.Read in encoding/binary provides mechanisms to convert byte arrays to datatypes.. Note that Network Byte Order is BigEndian, so in this case, you'll want to specify binary.BigEndian.. package main import ( "bytes" "encoding/binary" "fmt" ) func main() { var myInt int b := []byte{0x18, 0x2d} // This could also be a stream buf := bytes.NewReader(b) err := binary.Read(buf, binary.BigEndian ...

  5. Golang byte and bytes package| Scalent

    Size and Range of byte : A byte in Golang occupies 8 bits of memory and can represent values ranging from 0 to 255. Usage: The byte type is extensively used in Golang for handling raw binary data, reading from and writing to files, network communication, and encoding/decoding operations. Example Usage in Golang:

  6. Go Slices: usage and internals

    The slice type is an abstraction built on top of Go's array type, and so to understand slices we must first understand arrays. An array type definition specifies a length and an element type. For example, the type [4]int represents an array of four integers. An array's size is fixed; its length is part of its type ([4]int and [5]int are ...

  7. Arrays, slices (and strings): The mechanics of 'append'

    Here we see that the contents of a slice argument can be modified by a function, but its header cannot. The length stored in the slice variable is not modified by the call to the function, since the function is passed a copy of the slice header, not the original. Thus if we want to write a function that modifies the header, we must return it as a result parameter, just as we have done here.

  8. Go Walkthrough: bytes + strings

    In the previous post we covered byte streams but sometimes we need to work with bounded, in-memory byte slices instead. While working with a list of bytes seems simple enough, there are a lot of edge cases and common operations that make using the bytes package worthwhile. We're also going to lump in the strings package in this post since its API is nearly identical although for use with ...

  9. Binary Handling and Byte Order in Go: An Easy-to-Understand Guide

    In converting from int to byte, the int data is truncated to take only the lowest byte value. To check the byte order of your computer, you can convert an int to a byte and see the result. For example: package main import ("fmt") func main() {s := int32(0x12345678) b := byte(s) fmt.Printf("0x%x\n", b)} Output: 0x78

  10. bytes package

    func (b * Buffer) Bytes() [] byte. Bytes returns a slice of length b.Len () holding the unread portion of the buffer. The slice is valid for use only until the next buffer modification (that is, only until the next call to a method like Buffer.Read, Buffer.Write, Buffer.Reset, or Buffer.Truncate).

  11. GO Bytes to String Conversion Best Practices [5 Methods]

    Different Methods for GO Bytes to String conversion. Direct conversion using type casting. Use the fmt.Sprintf function for string formatting.; Utilizing the strings.Builder for efficient concatenation in loops.; Applying the strconv package for conversion with numeric interpretation.; The bytes.Buffer helps you convert and manipulate byte slices.; Reads bytes from files into strings straight ...

  12. How to assign string to bytes array in Golang?

    The simple, easy, and safest way is to assign a string to bytes array is, []byte("String_Value") Consider the below example, // Go language program to assign string // to bytes array package main. import (. "fmt". ) // Main function func main() {. // Declare a byte array var b [] byte // Assigning the string to bytes array.

  13. How To Convert Data Types in Go

    The second line printed out is the byte slice that makes up the original string. The third line shows that the byte slice can be safely converted back into a string and printed back out. Conclusion. This Go tutorial demonstrated how to convert several of the important native data types to other data types, primarily through built-in methods.

  14. string and []byte conversion problem in golang

    You'll notice that if you don't use the type in reflect, then the output doesn't work again. This backfires and verifies that the compiler is indeed doing something special with *reflect.{Slice,String}Header.. Now that we've basically figured out the pitfalls of string and []byte conversions, here's a look at how to write accurate conversion code, although the compiler plays a few ...

  15. Why i can not assign int to byte

    The constant 22 is not an int - it's an untyped constant. These can take on any numeric type depending on the context. In this case it will become a byte constant since it's used in a byte context. A numeric integer constant will default to the int type if there is no context (var foo = 22 // foo is now int), which is what you're thinking of.

  16. Feature: provide no-copy conversion from []byte to string #25484

    But in general, if you want to do this in your code, go for it. #19367 is a proposal to make this a bit nicer/safer. We don't want to provide this functionality (unsafe-converting a []byte to string) in the standard library because it lets people create mutable strings. Lots of packages assume strings are immutable, and may behave badly if the ...

  17. What's in an (Alias) Name?

    To top things off, Go's predeclared types (int, string and so on) can only be accessed through their names, and like defined types and type parameters, are different if their names are different (ignoring for a moment the byte and rune alias types). The predeclared types truly are named types.

  18. Golang: Deep and Shallow Copy a Slice

    Assignment a existed slice to a new variable. By assignment, the memory address of the backing array is the same for both of src and dst slices. You can access the source code here. ... Golang: Heap data structure. Heap is a completely binary tree and the root node has the smallest/largest value. It can also represented in the form of an array.

  19. go

    I have this code: hashChannel <- []byte(md5.Sum(buffer.Bytes())) And I get this error: cannot convert md5.Sum(buffer.Bytes()) (type [16]byte) to type []byte. Even without the explicit conversion this does not work. I can keep the type [16]byte as well, but at some point I need to convert it, as I'm sending it over a TCP connection:

  20. Step-by-Step Guide to Building a Blockchain with Go (Golang)

    Go, also known as Golang, is a programming language developed by Google, celebrated for its efficiency and scalability in software development. As a statically typed, compiled language, Go translates code directly into machine language, resulting in faster execution—something blockchain networks critically need.

  21. How to fix assign []byte of data in multiple assignment

    The return type of your function is of type byte, whereas the return type of ioutil.ReadAll is []byte. Those types do not match, where one is a byte and the other is a slice of bytes. Change the return type of data to []byte, assuming that is what you wanted in the first place. var bearer = "Bearer " + token. res, err := http.Get(url)