Wechat search [brain into fried fish] follow this fried fish with fried liver. In this paper, making github.com/eddycjy/blo… Already included, there are my series of articles, materials and open source Go books.

Hello, I’m fried fish.

It’s a weekend, although it’s only one day. Share a quick update for Go1.17. Add one fish sucking tip a day!

In Go, a slice contains a reference to its supported array, whether that array exists somewhere as a separate variable or is simply an anonymous array allocated to support sharding.

The basic structure of the slices is as follows:

// runtime/slice.go
type slice struct {
	array unsafe.Pointer // A pointer to the underlying array
	len   int / / the length
	cap   int / / capacity
}
Copy the code

The current way slicing supports arrays can lead to interesting memory leaks or surprising changes to your slicing.

Another important point is that before Go 1.16 or earlier, there was no safe way to convert from slice type to array type.

We can only do this by calling the standard library reflect or unsafe, and by writing unsafe code:

(* [10]byte)(unsafe.Pointer(&b[0]))
Copy the code

Unsafe is obviously unelegant, and even the authorities themselves don’t recommend using unsafe, which can lead to fatal errors if handled erratically.

In fact, back in 2009, shortly after Go was released (and long before Go 1.0 was released), a question was raised to solve this problem:

Finally, in the upcoming Go 1.17, this will be possible because of a series of changes, starting with commit-ID # 1C268431F4, that update the specification:

The description in the new specification is straightforward:

Converting a slice to an array pointer yields a pointer to the underlying array of the slice. If the length of the slice is less than the length of the array, a run-time panic occurs.

  • If the length of the slice is longer than the length of the array, it is harmless and will work fine.
  • If you count slices as long, it means that your array will not be able to access all the supported arrays of the original slice.

In addition, the specification provides some new examples that we can use in Go1.17:

s := make([]byte.2.4)
s0 := (*[0]byte)(s)      // s0 ! = nil
s2 := (*[2]byte)(s)      // &s2[0] == &s[0]
s4 := (*[4]byte)(s)      // panics: len([4]byte) > len(s)

var t []string
t0 := (*[0]string)(t)    // t0 == nil
t1 := (*[1]string)(t)    // panics: len([1]string) > len(s)
Copy the code
  • Conversion of variable S2: it converts the array at the bottom of the slice. This conversion does not (and cannot) allocate a new array, thus ensuring its efficiency.
  • Conversion of the variables s0 and t0: this converts a non-empty fragment to a zero-length array. Even though you can’t do anything with an array of length 0, you still have to give a valid pointer, which is nil.

It is important to note that there is no way to check for panic events, such as transgressions, as type assertions do. If you think you might have a fragment that is too short and could cause a panic event, you need to use if to anticipate.

The Library will also be updated to support conversion from slicing to array Pointers, so if you’re doing conversion work with Reflect, you’re advised to read the notes in this submission.

Do you have any other thoughts or aspirations about the type conversion aspect of Go, or have you stepped into any pitfalls?

Welcome to leave a message in the comments section.

If you have any questions, welcome feedback and communication in the comments section. The best relationship is mutual achievement. Your praise is the biggest motivation for the creation of fried fish, thank you for your support.

This article is constantly updated. You can search “Brain into fried fish” on wechat to read it. Reply [000] There are the answers and materials for the interview algorithm of first-line big factories that I prepared. In this paper, making github.com/eddycjy/blo… Star has been included, welcome to urge more.