"Go Language Lesson 1" Course Study Notes (8)

basic data type

What are the numeric types natively supported by Go?

  • The types of Go language can be roughly divided into three types: basic data types, composite data types and interface types.
    • Among them, the most used in our daily Go coding is the basic data type, and the most used basic data type is the numerical type.

integer

  • Integers in the Go language are mainly used to represent integer quantities in the real world. It can be divided into platform-independent integers and platform-dependent integers. The main difference between them is whether the lengths of these integer types are consistent under different CPU architectures or operating systems.
    • platform-independent integer
      • They are fixed in length under any CPU architecture or under any operating system.
        insert image description here
      • The essential difference between signed integers (int8-int64) and unsigned integers (uint8-uint64) is whether the highest binary bit (bit) is interpreted as a sign bit, which affects unsigned integers and signed integers. Type range of values.
      • Go uses 2's complement (Two's Complement) as the bit encoding method for integers. Therefore, we cannot simply regard the highest bit as a negative sign, and regard the value represented by the remaining bits as the value behind the negative sign. The complement code of Go is obtained by inverting the original code bit by bit and then adding 1.
    • platform-dependent integer
      • Platform-independent integers correspond to platform-dependent integers, and their lengths will vary depending on the operating platform.
      • Go language natively provides three platform-related integer types, they are int, uint and uintptr.
        insert image description here
      • Since the lengths of these three types are platform-dependent, we must not strongly rely on the lengths of these types when writing code with portability requirements.
      • If you don't know the size of these three types on the target operating platform, you can get them through the SizeOf function provided by the unsafe package.
  • Integer overflow problem
    • If the integer type is involved in an operation and the result exceeds the value boundary of the integer type, we say that an integer overflow problem has occurred.
    • Since the integer type cannot represent the "result" after it overflows, the value of the corresponding integer variable will still fall within its value range after overflow occurs, but the result value does not match our expectations, resulting in program logic error.
  • Literal values ​​and formatted output
    • The Go language has inherited the grammatical form of the C language about the number literal value (Number Literal) from the beginning of its design.
    • Earlier Go versions supported decimal, octal, and hexadecimal numeric literals.
    • In Go 1.13, Go added support for binary literals and two forms of octal literals.
    • To improve the readability of literal values, Go version 1.13 also supports adding a number separator "_" in literal values. The separator can be used to group numbers to improve readability.
    • Conversely, we can also use the formatted output function of the fmt package in the standard library to output an integer variable in different bases.

floating point

  • binary representation of floating point
    • The Go language provides two floating-point types, float32 and float64 , which correspond to single-precision and double-precision floating-point numeric types respectively.
      • However, the float type is not provided in the Go language .
      • In other words, the floating-point types provided by Go are all platform-independent.
      • Whether it is float32 or float64, the default value of their variables is 0.0. The difference is that the memory space they occupy is different, and the range and precision of floating-point numbers that can be represented are also different.
    • The binary representation of floating-point numbers in memory (Bit Representation) is much more complicated than that of integers:insert image description here
      • The binary representation of a floating-point number in memory is divided into three parts: the sign bit, the exponent (that is, the converted exponent), and the mantissa. A floating point number represented like this is equal to: ( − 1 ) s ∗ 1. M ∗ 2 E − offset (-1)^s * 1.M * 2 ^{E-offset}(1)s1.M2Eoffset
        • When the sign bit is 1, the floating point value is negative;
        • When the sign bit is 0, the floating point value is positive.
        • The offset in the formula is called the exponent offset value.
      • Differences between single-precision (float32) and double-precision (float64) floating-point numbers in exponent and mantissa:
        insert image description here
        • The single-precision floating-point type (float32) allocates 1 bit for the sign bit, 8 bits for the exponent, and the remaining 23 bits for the mantissa.
        • For the double-precision floating-point type, except that the length of the sign bit is the same as that of the single-precision floating-point type, the length of the other two parts is much larger than that of the single-precision floating-point type. The number of bits available for the order code is 11, and the mantissa has even more There are 52 bits.
  • Literal values ​​and formatted output
    • Go floating-point type literals can be roughly divided into two categories, one is the form of floating-point values ​​that are expressed directly in decimal. In this category, we can directly determine its floating-point value through the literal value.
    • The other is the scientific notation form. For floating-point literals expressed in scientific notation, we need to perform certain conversions to determine their floating-point values. And here, the form of scientific notation is divided into two types expressed in decimal form and hexadecimal form.
      6674.28e-2 // 6674.28 * 10^(-2) = 66.742800
      .12345E+5 // 0.12345 * 10^5 = 12345.000000
      0x2.p10 // 2.0 * 2^10 = 2048.000000
      0x1.Fp+0 // 1.9375 * 2^0 = 1.937500
      

plural type

  • Go provides two types of complex numbers, they are complex64 and complex128, the real part and imaginary part of complex64 are float32 type, and the real part and imaginary part of complex128 are float64 type. If a complex number is not explicitly assigned a type, then its default type is complex128.
  • Regarding the representation of complex literal values, we actually have three methods:
    • First, we can directly initialize a complex type variable with a complex literal value: var c = 5 + 6i.
    • Second, Go also provides the complex function, which is convenient for us to create a complex128 type value: var c = complex(5, 6) // 5 + 6i.
    • Third, you can also use the predefined functions real and imag provided by Go to get the real and imaginary parts of a complex number, and the return value is a floating point type:
      var c = complex(5, 6) // 5 + 6i
      r := real(c) // 5.000000
      i := imag(c) // 6.000000
      

string type

  • In Go, the string type is string.
    • The Go language unifies the abstraction of "strings" through the string type.
    • In this way, whether it is a string constant, a string variable, or a string literal value appearing in the code, their type is uniformly set to string.
    • The data of string type is immutable, which improves the concurrency security and storage utilization of strings.
  • Composition of Go strings
    • The string value in Go language is also a nullable byte sequence, and the number of bytes in the byte sequence is called the length of the string. Each byte is just isolated data and does not express meaning.
    • Strings are composed of a nullable sequence of characters.
  • rune types and character literals
    • Go uses the rune type to represent a Unicode code point. Rune is essentially an alias type of int32 type, which is completely equivalent to int32 type.
    • A rune instance is a Unicode character, and a Go string can also be regarded as a collection of rune instances. We can initialize a rune variable with a character literal.
    • In Go, there are several representations for character literals, the most common being character literals enclosed in single quotes.
    • We can also use the Unicode-specific escape character \u or \U as a prefix to represent a Unicode character.
    • Since the rune representing the code point is essentially an integer, we can also use the integer value to directly assign a value to the rune variable as a character literal.
  • string literal
    • A string is a collection of characters. We need to replace single quotes representing a single character with double quotes representing a string of multiple characters.
    • The string type is actually a "descriptor". It does not really store string data itself, but only consists of a pointer to the underlying storage and the length field of the string.
    • We will not bring too much overhead by passing the string type directly through function/method parameters. Because what is passed in is just a "descriptor", not real string data.
  • Common operations on Go string types
    • subscript
      • In the implementation of strings, it is the underlying array that actually stores data.
      • Subscripting a string is essentially equivalent to subscripting an underlying array.
        var s = "中国人"
        fmt.Printf("0x%x\n", s[0]) // 0xe4:字符“中” utf-8编码的第一个字节
        
      • With subscripting, we get the bytes at a particular subscript in the string, not the characters.
    • character iteration
      • Go has two forms of iteration: regular for iteration and for range iteration.
      • The results obtained by operating on strings through these two forms of iteration are different.
      • The operation on strings through regular for iteration is a byte perspective iteration. The result of each round of iteration is a byte that makes up the content of the string and the subscript value where the byte is located, which is also the same as Equivalent to iterating over the underlying array of strings.
      • Through for range iteration, what we get each round of iteration is the code point value of the Unicode character in the string, and the offset value of the character in the string.
      • We can obtain the number of characters in the string through such iterations, but through the built-in function len provided by Go, we can only obtain the length (number of bytes) of the string content.
      • A more specialized way to get the number of characters in a string is to call the RuneCountInString function in the UTF-8 package of the standard library.
    • string concatenation
      • Go natively supports string concatenation via the +/+= operators.
      • While the developer experience with string concatenation via +/+= is the best, concatenation performance may not be the fastest.
      • In addition to this method, Go also provides strings.Builder, strings.Join, fmt.Sprintf and other functions to perform string concatenation operations .
    • string comparison
      • Go string types support various comparison operators, including ==, !=, >=, <=, >, and <.
      • In the comparison of strings, Go uses a lexicographical comparison strategy to compare two string type variables byte by byte from the beginning of each string.
        • When the first different element appears between the two strings, the comparison is over, and the comparison result of these two elements will be used as the final comparison result of the strings.
        • If two strings have different lengths, the string with a smaller length will be filled with empty elements, and empty elements are smaller than other non-empty elements.
      • Given that the Go string type is immutable, if the lengths of two strings are not the same, then we don't need to compare the specific string data, and we can also conclude that the two strings are different. But if the two strings have the same length, it is necessary to further judge whether the data pointer points to the same underlying storage data. If they are still the same, then we can say that the two strings are equivalent. If they are different, then we need to further compare the actual data content.
    • string conversion
      • Go supports two-way conversion between strings and byte slices, strings and rune slices, and this conversion does not need to call any function, just use explicit type conversion.

Guess you like

Origin blog.csdn.net/fangzhan666/article/details/132343891