Golang程序运行后bash提示符出现奇怪符号问题

Golang程序运行后bash提示符出现奇怪符号问题 当我的程序完成后,bash提示符显示如下(最后一行):

...
{Name:Herriman Country:United States Subcountry:Utah Geonameid:5775782}
{Name:Highland Country:United States Subcountry:Utah Geonameid:5775863}
{Name:Holladay Country:United States Subcountry:Utah Geonameid:5776008}

^[[?1;2cuser@comp:~/go/src/cities$ 1;2c1;2c1;2c1;2c1;2c

以下是代码:

for _, c := range cities {
    fmt.Printf("%+v\n", c)
}
fmt.Printf("\n")

为什么会产生这些符号?

如果我从操作系统终端运行该文件,bash提示符会显示为:

user@comp:~/go/src/cities$ 62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c62;c


更多关于Golang程序运行后bash提示符出现奇怪符号问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

你的终端和/或CSV库无法处理CSV文件中使用的编码。

更多关于Golang程序运行后bash提示符出现奇怪符号问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


您可以使用类似 unigo 的工具对输出进行预处理,将 Unicode 转换为 rune 类型。

你好,@cinematik,这不是一个完整的程序,所以我无法测试它来确认是否能重现问题。根据你发布的内容,我目前推测可能在你打印输出的某个地方(可能是在上面的代码片段中,也可能不是)存在一些二进制数据,这些数据正在影响终端。

我发现是源文件产生了这样的结果。我有一个结构如下的巨大CSV文件:

Don Luan,Vietnam,BУЌnh PhЦАсЛ›c,1582436

我使用 github.com/jszwec/csvutil 对其进行反序列化,上述输入在控制台给我的输出是:

user@comp:~/go/src/cities$ 1;2c

接下来我将源文件内容简化为:

Don Luan,Vietnam,Л›c,1582436

输出结果:

{Name:Don Luan Country:Vietnam Subcountry:Л Geonameid:1582436} user@comp:~/go/src/cities$ 1;2c

当我把光标放在CSV文件中这个字符的中间时:

Л›c

我需要按两次退格键才能删除 Л› 字符,这很奇怪,不是吗?

这个问题通常是由于终端转义序列未正确重置导致的。当程序输出包含ANSI转义序列但未正确结束时,终端会保持特殊状态,导致提示符显示异常。

在你的代码中,问题可能出现在输出包含特殊字符或程序异常退出时。以下是解决方案:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

type City struct {
    Name      string
    Country   string
    Subcountry string
    Geonameid int
}

func main() {
    // 设置信号处理,确保程序正常退出时重置终端
    setupSignalHandler()
    
    cities := []City{
        {Name: "Herriman", Country: "United States", Subcountry: "Utah", Geonameid: 5775782},
        {Name: "Highland", Country: "United States", Subcountry: "Utah", Geonameid: 5775863},
        {Name: "Holladay", Country: "United States", Subcountry: "Utah", Geonameid: 5776008},
    }
    
    for _, c := range cities {
        fmt.Printf("%+v\n", c)
    }
    
    // 确保输出缓冲区刷新
    os.Stdout.Sync()
}

func setupSignalHandler() {
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-c
        resetTerminal()
        os.Exit(0)
    }()
}

func resetTerminal() {
    // 发送重置序列
    fmt.Print("\033c")
    os.Stdout.Sync()
}

更简单的解决方案是使用os.Stdout直接输出:

package main

import (
    "os"
)

func main() {
    cities := []City{
        {Name: "Herriman", Country: "United States", Subcountry: "Utah", Geonameid: 5775782},
        {Name: "Highland", Country: "United States", Subcountry: "Utah", Geonameid: 5775863},
        {Name: "Holladay", Country: "United States", Subcountry: "Utah", Geonameid: 5776008},
    }
    
    for _, c := range cities {
        os.Stdout.WriteString(fmt.Sprintf("%+v\n", c))
    }
    
    os.Stdout.Sync()
}

如果问题仍然存在,可以在程序结束时显式重置终端:

package main

import (
    "fmt"
    "os"
)

func main() {
    defer resetTerminal()
    
    cities := []City{
        {Name: "Herriman", Country: "United States", Subcountry: "Utah", Geonameid: 5775782},
        {Name: "Highland", Country: "United States", Subcountry: "Utah", Geonameid: 5775863},
        {Name: "Holladay", Country: "United States", Subcountry: "Utah", Geonameid: 5776008},
    }
    
    for _, c := range cities {
        fmt.Printf("%+v\n", c)
    }
}

func resetTerminal() {
    fmt.Print("\033[0m")  // 重置所有属性
    fmt.Print("\033[?25h") // 显示光标
    os.Stdout.Sync()
}

这些代码示例通过确保终端状态正确重置来解决提示符显示异常的问题。

回到顶部