• 转载 Golang []byte与string转换的一个误区


    Golang []byte与string转换的一个误区

    https://www.oyohyee.com/post/Note/golang_byte_to_string/

     2019-08-10 23:46:31

     610

    在实现[]byte转换string的过程中,发现了一个很容易理解错误的地方。
    注意:这里要区分0'''0'的区别。其中前两者等价,是内存中实际的值。而'0'是显示的值,其在内存中实际是48,也即0x30

    在C语言中,字符串的结尾是'',也即字节为0的字符。

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char s[] = {'a', 'b', 'c', '', '', 'd'};
        printf("%d %d %s
    ", strlen(s), sizeof(s), s);
       
        return 0;
    }


    这个程序输出的内容是3 6 abc






    而在Go语言中,字符串仅仅把对应字节为0的字符认为是空字符,不显示但是仍然占用长度。

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        b := []byte{'a', 'b', 'c', 0, 0, 'd'}
        s := string(b)
        fmt.Printf("%d %s %s
    ", len(s), s, b)
    }


    这个程序输出的内容是6 abcd abcd


    0在C语言以及Go语言不同的表现在大部分情况下不会造成问题,但是当使用io.Reader(b []byte)时,如果传入的字节数组b本身长度大于reader可读到的长度,则会导致末尾被0补齐。当直接使用string(b)强制类型转换时会导致显示上看似无问题,但是实际上字符串并不相同。
    要解决这个问题需要对[]bytestring的转换过程进行一个封装。

    这里实现了针对两种情况的解决方案,前者是遇到0就结束转换,后者则是忽略所有的0并将剩余部分拼接

    // String 将 `[]byte` 转换为 `string`
    func String(b []byte) string {
        for idx, c := range b {
            if c == 0 {
                return string(b[:idx])
            }
        }
        return string(b)
    }
    
    // StringWithoutZero 将 `[]byte` 转换为 `string`
    func StringWithoutZero(b []byte) string {
        s := make([]rune, len(b))
        offset := 0
        for i, c := range b {
            if c == 0 {
                offset++
            } else {
                s[i-offset] = rune(c)
            }
        }
        return string(s[:len(b)-offset-1])
    }
  • 相关阅读:
    myBatis学习笔记(10)——使用拦截器实现分页查询
    电影院的设计与实现(改进更新)
    软件设计师自我修炼1:怎样让用户对软件产生依赖
    jQuery.ajax()方法中參数具体解析
    王立平--Gallery:实现图片的左右滑动
    USB设备驱动概述
    Android中的多线程编程(一)附源代码
    Shannon-Fano-Elias编码的C语言实现
    互联网协议入门深入
    linux内核中创建线程方法【转】
  • 原文地址:https://www.cnblogs.com/saolv/p/11768903.html
Copyright © 2020-2023  润新知