Golang在Windows系统中彩色文本显示异常问题
Golang在Windows系统中彩色文本显示异常问题 我有这段代码,但它只在Linux上有效。我需要怎么做才能让它能在Windows、Linux、Mac等系统上运行?
package main
import "fmt"
var (
Info = Teal
Warn = Yellow
Fata = Red
)
var (
Black = Color("\033[1;30m%s\033[0m")
Red = Color("\033[1;31m%s\033[0m")
Green = Color("\033[1;32m%s\033[0m")
Yellow = Color("\033[1;33m%s\033[0m")
Purple = Color("\033[1;34m%s\033[0m")
Magenta = Color("\033[1;35m%s\033[0m")
Teal = Color("\033[1;36m%s\033[0m")
White = Color("\033[1;37m%s\033[0m")
)
func Color(colorString string) func(...interface{}) string {
sprint := func(args ...interface{}) string {
return fmt.Sprintf(colorString,
fmt.Sprint(args...))
}
return sprint
}
func main() {
fmt.Println(Info("hello, world!"))
}
更多关于Golang在Windows系统中彩色文本显示异常问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我曾希望有一个适用于所有操作系统的简便方法。
更多关于Golang在Windows系统中彩色文本显示异常问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你有任何示例吗?或者我可以在哪里找到相关信息?
可能存在一些库,它们对系统进行了封装,让你可以直接使用它们的API。
不过,到目前为止,我还没有在Go中使用过这样的库。
上次使用是在Ruby中,效果并不好。它的API不像Windows原生的那样笨拙,但也不像Linux的那么直接。而且它在每个字符后都会刷新流……体验并不好……
通常,最简单的做法是在Windows上干脆不使用颜色。
Windows 为什么比 Linux 复杂得多,因为 Windows 需要一些函数调用来处理字符流。包括每隔几个字节就显式刷新,以确保新颜色能从正确的字符开始应用。
不过据我所知,现代的 Windows 终端(在 Win10 的某个版本中引入)能够理解用于着色的 ANSI 代码。
也许这仅限于 Powershell?不太确定……
有一个库演示了如何在 Windows 上实现这一点。其核心在于通过系统调用来告知操作系统如何表现。
fatih/color
Go (golang) 的颜色包。通过在 GitHub 上创建账户来为 fatih/color 的开发做出贡献。
真正的魔法在于:
mattn/go-colorable/blob/master/colorable_windows.go
// +build windows
// +build !appengine
package colorable
import (
"bytes"
"io"
"math"
"os"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/mattn/go-isatty"
)
const (
foregroundBlue = 0x1
此文件已被截断。显示原文
在Windows系统中,ANSI转义序列默认不被支持。需要使用第三方库或系统调用来启用控制台虚拟终端序列。以下是使用github.com/inancgumus/screen库的解决方案:
package main
import (
"fmt"
"runtime"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
)
func enableWindowsANSI() bool {
if runtime.GOOS != "windows" {
return true
}
handle := syscall.Handle(os.Stdout.Fd())
var mode uint32
err := syscall.GetConsoleMode(handle, &mode)
if err != nil {
return false
}
mode |= 0x0004 // ENABLE_VIRTUAL_TERMINAL_PROCESSING
ret, _, err := procSetConsoleMode.Call(uintptr(handle), uintptr(mode))
return ret != 0
}
var (
Info = Teal
Warn = Yellow
Fata = Red
)
var (
Black = Color("\033[1;30m%s\033[0m")
Red = Color("\033[1;31m%s\033[0m")
Green = Color("\033[1;32m%s\033[0m")
Yellow = Color("\033[1;33m%s\033[0m")
Purple = Color("\033[1;34m%s\033[0m")
Magenta = Color("\033[1;35m%s\033[0m")
Teal = Color("\033[1;36m%s\033[0m")
White = Color("\033[1;37m%s\033[0m")
)
func Color(colorString string) func(...interface{}) string {
return func(args ...interface{}) string {
return fmt.Sprintf(colorString, fmt.Sprint(args...))
}
}
func main() {
if !enableWindowsANSI() {
fmt.Println("警告: 无法启用Windows ANSI支持,颜色可能无法显示")
}
fmt.Println(Info("hello, world!"))
fmt.Println(Warn("这是一个警告"))
fmt.Println(Fata("这是一个错误"))
}
或者使用跨平台的github.com/fatih/color库:
package main
import (
"github.com/fatih/color"
)
var (
Info = color.New(color.FgCyan).SprintFunc()
Warn = color.New(color.FgYellow).SprintFunc()
Fata = color.New(color.FgRed).SprintFunc()
)
func main() {
fmt.Println(Info("hello, world!"))
fmt.Println(Warn("这是一个警告"))
fmt.Println(Fata("这是一个错误"))
}
对于更简单的解决方案,可以使用条件编译:
// +build !windows
package main
import "fmt"
var (
Black = Color("\033[1;30m%s\033[0m")
Red = Color("\033[1;31m%s\033[0m")
// ... 其他颜色定义
)
// +build windows
package main
import "fmt"
var (
Black = fmt.Sprintf
Red = fmt.Sprintf
// ... Windows下禁用颜色
)
使用golang.org/x/term检测终端能力:
package main
import (
"fmt"
"golang.org/x/term"
"os"
)
func isColorSupported() bool {
return term.IsTerminal(int(os.Stdout.Fd()))
}
func Color(colorString string) func(...interface{}) string {
return func(args ...interface{}) string {
if !isColorSupported() {
return fmt.Sprint(args...)
}
return fmt.Sprintf(colorString, fmt.Sprint(args...))
}
}


