Home > Backend Development > Golang > Why *(*string)(unsafe.Pointer(&b)) doesn't work with bufio.Reader

Why *(*string)(unsafe.Pointer(&b)) doesn't work with bufio.Reader

王林
Release: 2024-02-09 19:54:17
forward
1059 people have browsed it

为什么 *(*string)(unsafe.Pointer(&b)) 不适用于 bufio.Reader

In the Go language, we often use type conversion to convert data types. For example, convert a slice of type []byte to a string of type string. Normally, we can use the `string()` function to perform type conversion, but in some special cases, this method can cause problems. In the Go language, the `(string)(unsafe.Pointer(&b))` method is called the "magic pointer" method, which is used to convert a []byte type slice into a string type string. However, this method does not work for the bufio.Reader type. why? Let's answer this question.

Question content

I have a file. It has some ip

1.1.1.0/24
1.1.2.0/24
2.2.1.0/24
2.2.2.0/24
Copy after login

I read this file for slicing and parse the []byte into string using *(*string)(unsafe.pointer(&b)) but it doesn't work

func testinitiprangefromfile(t *testing.t) {
   filepath := "/tmp/test"
   file, err := os.open(filepath)
   if err != nil {
      t.errorf("failed to open ip range file:%s, err:%s", filepath, err)
   }
   reader := bufio.newreader(file)
   ranges := make([]string, 0)
   for {
      ip, _, err := reader.readline()
      if err != nil {
         if err == io.eof {
            break
         }
         logger.fatalf("failed to read ip range file, err:%s", err)
      }
      t.logf("ip:%s", *(*string)(unsafe.pointer(&ip)))
      ranges = append(ranges, *(*string)(unsafe.pointer(&ip)))
   }

   t.logf("%v", ranges)
}
Copy after login

result:

task_test.go:71: ip:1.1.1.0/24
    task_test.go:71: ip:1.1.2.0/24
    task_test.go:71: ip:2.2.1.0/24
    task_test.go:71: ip:2.2.2.0/24
    task_test.go:75: [2.2.2.0/24 1.1.2.0/24 2.2.1.0/24 2.2.2.0/24]
Copy after login

Why is 1.1.1.0/24 changed to 2.2.2.0/24?

Change

*(*string)(unsafe.Pointer(&ip))
Copy after login

to string(ip) it works

Workaround

So while reinterpreting the slice header as a string header, the way you did it is absolutely crazy , and cannot be guaranteed to work properly, but this is only an indirect cause of the problem. p>

The real problem is that you retain a pointer to the return value of bufio/Reader.ReadLine() but the documentation for that method says "The returned buffer is only valid until the next call to ReadLine." This means that the reader is free to reuse that memory later, which is what is happening.

When you do the conversion the right way, string(ip), Go copies the contents of the buffer into a newly created string that will still be valid in the future. However, when you type a slice pun into a string, you retain the exact same pointer, which stops working once the reader refills its buffer.

If you decide to use pointer tricking as a performance hack to avoid copies and allocations...that's too bad. The reader interface forces you to copy the data anyway, so you should just use string().

The above is the detailed content of Why *(*string)(unsafe.Pointer(&b)) doesn't work with bufio.Reader. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template