Go语言跨平台GUI工具包tk9.0

不得不说,这名字起的.....tk9.0是一个用Go语言编写的跨平台GUI工具包,它使用Tcl/Tk作为底层图形库,无需CGo,这意味着您可以使用它来创建原生跨平台应用程序,而无需依赖于C语言编译器

优势介绍:

  • 跨平台: tk9.0支持Windows、macOS、Linux和FreeBSD等多个平台,您可以轻松地将您的应用程序移植到不同的操作系统上。
  • 无需CGo: tk9.0的实现完全使用Go语言编写,无需依赖于CGo,这意味着您不需要安装任何C语言编译器,可以轻松地将您的应用程序部署到不同的环境中。
  • 易于使用: tk9.0提供了简洁直观的API,方便您快速上手并创建自己的GUI应用程序。
  • 丰富的功能: tk9.0提供了丰富的控件,包括按钮、标签、文本框、列表框、滚动条、菜单等,可以满足您各种开发需求。
  • 高度可定制: tk9.0允许您自定义控件的外观和行为,以满足您的应用程序的特定需求。

这是一些官方示例

这些示例中写的都比较简单,并没有过多的多窗口或复杂的使用,但是常用的窗体内容的展示都有了. 开始展示

项目地址 Gitlab仓库

示例1. 图片+按钮

package main

import _ "embed"
import . "modernc.org/tk9.0"

//go:embed gopher.png
var gopher []byte

func main() {
    Pack(Label(Image(NewPhoto(Data(gopher)))),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

photo.png

示例2. 菜单

package main

import (
    "fmt"
    . "modernc.org/tk9.0"
    "runtime"
)

func main() {
    menubar := Menu()

    fileMenu := menubar.Menu()
    fileMenu.AddCommand(Lbl("New"), Underline(0), Accelerator("Ctrl+N"))
    fileMenu.AddCommand(Lbl("Open..."), Underline(0), Accelerator("Ctrl+O"), Command(func() { GetOpenFile() }))
    Bind(App, "<Control-o>", Command(func() { fileMenu.Invoke(1) }))
    fileMenu.AddCommand(Lbl("Save"), Underline(0), Accelerator("Ctrl+S"))
    fileMenu.AddCommand(Lbl("Save As..."), Underline(5))
    fileMenu.AddCommand(Lbl("Close"), Underline(0), Accelerator("Crtl+W"))
    fileMenu.AddSeparator()
    fileMenu.AddCommand(Lbl("Exit"), Underline(1), Accelerator("Ctrl+Q"), ExitHandler())
    Bind(App, "<Control-q>", Command(func() { fileMenu.Invoke(6) }))
    menubar.AddCascade(Lbl("File"), Underline(0), Mnu(fileMenu))

    editMenu := menubar.Menu()
    editMenu.AddCommand(Lbl("Undo"))
    editMenu.AddSeparator()
    editMenu.AddCommand(Lbl("Cut"))
    editMenu.AddCommand(Lbl("Copy"))
    editMenu.AddCommand(Lbl("Paste"))
    editMenu.AddCommand(Lbl("Delete"))
    editMenu.AddCommand(Lbl("Select All"))
    menubar.AddCascade(Lbl("Edit"), Underline(0), Mnu(editMenu))

    helpMenu := menubar.Menu()
    helpMenu.AddCommand(Lbl("Help Index"))
    helpMenu.AddCommand(Lbl("About..."))
    menubar.AddCascade(Lbl("Help"), Underline(0), Mnu(helpMenu))

    App.WmTitle(fmt.Sprintf("%s on %s", App.WmTitle(""), runtime.GOOS))
    App.Configure(Mnu(menubar), Width("8c"), Height("6c")).Wait()
}

苹果系统中它展示在顶部菜单栏中,并不在软件窗口里
menu.png

示例3. 文本内容

package main

import . "modernc.org/tk9.0"

func main() {
    var scroll *TScrollbarWidget
    t := Text(Font("helvetica", 10), Yscrollcommand(func(e *Event) { e.ScrollSet(scroll) }), Setgrid(true), Wrap("word"), Padx("2m"), Pady("2m"))
    scroll = TScrollbar(Command(func(e *Event) { e.Yview(t) }))
    Grid(t, Sticky("news"), Pady("2m"))
    Grid(scroll, Row(0), Column(1), Sticky("nes"), Pady("2m"))
    GridRowConfigure(App, 0, Weight(1))
    GridColumnConfigure(App, 0, Weight(1))
    Grid(TExit(), Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    t.TagConfigure("bgstipple", Background(Black), Borderwidth(0), Bgstipple(Gray12))
    t.TagConfigure("big", Font("helvetica", 12, "bold"))
    t.TagConfigure("bold", Font("helvetica", 10, "bold", "italic"))
    t.TagConfigure("center", Justify("center"))
    t.TagConfigure("color1", Background("#a0b7ce"))
    t.TagConfigure("color2", Foreground(Red))
    t.TagConfigure("margins", Lmargin1("12m"), Lmargin2("6m"), Rmargin("10m"))
    t.TagConfigure("overstrike", Overstrike(1))
    t.TagConfigure("raised", Relief("raised"), Borderwidth(1))
    t.TagConfigure("right", Justify("right"))
    t.TagConfigure("spacing", Spacing1("10p"), Spacing2("2p"), Lmargin1("12m"), Lmargin2("6m"), Rmargin("10m"))
    t.TagConfigure("sub", Offset("-2p"), Font("helvetica", 8))
    t.TagConfigure("sunken", Relief("sunken"), Borderwidth(1))
    t.TagConfigure("super", Offset("4p"), Font("helvetica", 8))
    t.TagConfigure("tiny", Font("times", 8, "bold"))
    t.TagConfigure("underline", Underline(1))
    t.TagConfigure("verybig", Font(CourierFont(), 22, "bold"))
    t.InsertML(`Text widgets like this one allow you to display information in a variety of styles. Display styles are controlled
using a mechanism called <bold>tags</bold>. Tags are just textual names that you can apply to one or more ranges of characters within a
text widget. You can configure tags with various display styles. If you do this, then the tagged characters will be displayed with the
styles you chose. The available display styles are:
<br><br><big>1. Font.</big> You can choose any system font, <verybig>large</verybig> or <tiny>small</tiny>.
<br><br><big>2. Color.</big> You can change either the <color1>background</color1> or <color2>foreground</color2> color, or
<color1><color2>both</color2></color1>.
<br><br><big>3. Stippling.</big> You can cause the <bgstipple>background</bgstipple> information to be drawn with a stipple fill instead
of a solid fill.
<br><br><big>4. Underlining.</big> You can <underline>underline</underline> ranges of text.
<br><br><big>5. Overstrikes.</big> You can <overstrike>draw lines through</overstrike> ranges of text.
<br><br><big>6. 3-D effects.</big> You can arrange for the background to be drawn with a border that makes characters appear either
<raised>raised</raised> or <sunken>sunken</sunken>.
<br><br><big>7. Justification.</big> You can arrange for lines to be displayed <br>left-justified <br><right>right-justified, or</right>
<br><center>centered.</center>
<br><br><big>8. Superscripts and subscripts.</big> You can control the vertical position of text to generate superscript effects like
10<super>n</super> or subscript effects like X<sub>i</sub>.
<br><br><big>9. Margins.</big> You can control the amount of extra space left on each side of the text
<br><br><margins>This paragraph is an example of the use of margins. It consists of a single line of text that wraps around on the
screen.  There are two separate left margin values, one for the first display line associated with the text line, and one for the
subsequent display lines, which occur because of wrapping. There is also a separate specification for the right margin, which is used to
choose wrap points for lines.</margins>
<br><br><big>10. Spacing.</big> You can control the spacing of lines with three separate parameters. "Spacing1" tells how much extra
space to leave above a line, "spacing3" tells how much space to leave below a line, and if a text line wraps, "spacing2" tells how much
space to leave between the display lines that make up the text line.
<br><spacing>These indented paragraphs illustrate how spacing can be used. Each paragraph is actually a single line in the text widget,
which is word-wrapped by the widget.</spacing>
<br><spacing>Spacing1 is set to 10 points for this text, which results in relatively large gaps between the paragraphs. Spacing2 is set
to 2 points, which results in just a bit of extra space within a pararaph. Spacing3 isn't used in this example.</spacing>
<br><spacing>To see where the space is, select ranges of text within these paragraphs. The selection highlight will cover the extra
space.</spacing>`)
    App.Center().Wait()
}

text.png

示例4. svg图片

package main

import . "modernc.org/tk9.0"

// https://en.wikipedia.org/wiki/SVG
const svg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="391" height="391" viewBox="-70.5 -70.5 391 391" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect fill="#fff" stroke="#000" x="-70" y="-70" width="390" height="390"/>
<g opacity="0.8">
    <rect x="25" y="25" width="200" height="200" fill="lime" stroke-width="4" stroke="pink" />
    <circle cx="125" cy="125" r="75" fill="orange" />
    <polyline points="50,150 50,200 200,200 200,100" stroke="red" stroke-width="4" fill="none" />
    <line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
</g>
</svg>`

func main() {
    Pack(Label(Image(NewPhoto(Data(svg)))),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

svg.png

示例5. 计算器

package main

import "github.com/expr-lang/expr"
import . "modernc.org/tk9.0"

func main() {
    out := Label(Height(2), Anchor("e"), Txt("(123+232)/(123-10)"))
    Grid(out, Columnspan(4), Sticky("e"))
    var b *ButtonWidget
    for i, c := range "C()/789*456-123+0.=" {
        b = Button(Txt(string(c)),
            Command(
                func() {
                    switch c {
                    case 'C':
                        out.Configure(Txt(""))
                    case '=':
                        x, err := expr.Eval(out.Txt(), nil)
                        if err != nil {
                            MessageBox(Icon("error"), Msg(err.Error()), Title("Error"))
                            x = ""
                        }
                        out.Configure(Txt(x))
                    default:
                        out.Configure(Txt(out.Txt() + string(c)))
                    }
                },
            ),
            Width(-4))
        Grid(b, Row(i/4+1), Column(i%4), Sticky("news"), Ipadx("1.5m"), Ipady("2.6m"))
    }
    Grid(b, Columnspan(2))
    App.Configure(Padx(0), Pady(0)).Wait()
}

calc.png

示例6. 字体

package main

import "fmt"
import "slices"
import . "modernc.org/tk9.0"

func main() {
    var scroll *TScrollbarWidget
    t := Text(Wrap("none"), Setgrid(true), Yscrollcommand(func(e *Event) { e.ScrollSet(scroll) }))
    scroll = TScrollbar(Command(func(e *Event) { e.Yview(t) }))
    fonts := FontFamilies()
    slices.Sort(fonts)
    Grid(t, Sticky("news"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    Grid(scroll, Row(0), Column(1), Sticky("nes"), Pady("2m"))
    GridRowConfigure(App, 0, Weight(1))
    GridColumnConfigure(App, 0, Weight(1))
    Grid(TExit(), Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    m := map[string]bool{}
    for i, font := range fonts {
        if m[font] {
            continue
        }
        m[font] = true
        tag := fmt.Sprintf("t%v", i)
        t.TagConfigure(tag, Font(NewFont(Family(font))))
        t.Insert("end", font+": ", "", "Lorem ipsum dolor sit amet, consectetur adipiscing elit...\n", tag)
    }
    App.Center().Wait()
}

font.png

示例7. 这个示例需要安装Gnuplot 5.4+

package main

import . "modernc.org/tk9.0"

var cm = int(TkScaling()*72/2.54 + 0.5)

func main() {
    Pack(Label(Image(NewPhoto(Width(20*cm), Height(15*cm)).Graph("set grid; splot x**2+y**2, x**2-y**2"))),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

splot.png

示例8 这个也需要安装 Gnuplot 5.4+

package main

import . "modernc.org/tk9.0"

// https://gnuplot.sourceforge.net/demo_5.4/hidden2.html
const script = `
set multiplot title "Interlocking Tori"
set title "PM3D surface\nno depth sorting"
set parametric
set urange [-pi:pi]
set vrange [-pi:pi]
set isosamples 50,20
set origin -0.02,0.0
set size 0.55, 0.9
unset key
unset xtics
unset ytics
unset ztics
set border 0
set view 60, 30, 1.5, 0.9
unset colorbox
set pm3d scansbackward
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) with pm3d,1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) with pm3d
set title "PM3D surface\ndepth sorting"
set origin 0.40,0.0
set size 0.55, 0.9
set colorbox vertical user origin 0.9, 0.15 size 0.02, 0.50
set format cb "%.1f"
set pm3d depthorder
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) with pm3d,1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) with pm3d
unset multiplot`

var cm = int(TkScaling()*72/2.54 + 0.5)

func main() {
    Pack(Label(Image(NewPhoto(Width(20*cm), Height(15*cm)).Graph(script))),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

tori.png

示例9 . 依旧要安装....

package main

import . "modernc.org/tk9.0"

// https://gnuplot.sourceforge.net/demo_5.4/surface2.9.gnu
const script = `
set dummy u, v
set key bmargin center horizontal Right noreverse enhanced autotitle nobox
set parametric
set view 50, 30, 1, 1
set isosamples 50, 20
set hidden3d back offset 1 trianglepattern 3 undefined 1 altdiagonal bentover
set style data lines
set xyplane relative 0
set title "Interlocking Tori" 
set grid
set urange [ -3.14159 : 3.14159 ] noreverse nowriteback
set vrange [ -3.14159 : 3.14159 ] noreverse nowriteback
set xrange [ * : * ] noreverse writeback
set x2range [ * : * ] noreverse writeback
set yrange [ * : * ] noreverse writeback
set y2range [ * : * ] noreverse writeback
set zrange [ * : * ] noreverse writeback
set cbrange [ * : * ] noreverse writeback
set rrange [ * : * ] noreverse writeback
set colorbox vertical origin screen 0.9, 0.2 size screen 0.05, 0.6 front  noinvert bdefault
NO_ANIMATION = 1
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) with lines,1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) with lines`

var cm = int(TkScaling()*72/2.54 + 0.5)

func main() {
    Pack(Canvas(Width(20*cm), Height(15*cm), Background(White)).Graph(script),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

tori_canvas.png

示例10 公式图

package main

import . "modernc.org/tk9.0"

func main() {
    tex := `$$\int _0 ^\infty {{\sin ax \sin bx}\over{x^2}}\,dx = {\pi a\over 2}$$`
    Pack(Label(Relief("sunken"), Image(NewPhoto(Data(TeX(tex, 2*TkScaling()*72/600))))),
        TExit(),
        Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    App.Center().Wait()
}

tex.png

示例11 文本中嵌入公式等小组件

package main

import . "modernc.org/tk9.0"
import _ "embed"

//go:embed gotk.png
var icon []byte

func main() {
    fontSize := int(10*TkScaling()/NativeScaling + 0.5)
    font := Font("helvetica", fontSize)
    var scroll *TScrollbarWidget
    t := Text(font, Height(15), Yscrollcommand(func(e *Event) { e.ScrollSet(scroll) }), Setgrid(true), Wrap("word"),
        Padx("4p"), Pady("12p"))
    scroll = TScrollbar(Command(func(e *Event) { e.Yview(t) }))
    Grid(t, Sticky("news"), Pady("2m"))
    Grid(scroll, Row(0), Column(1), Sticky("nes"), Pady("2m"))
    GridRowConfigure(App, 0, Weight(1))
    GridColumnConfigure(App, 0, Weight(1))
    Grid(Exit().Configure(font), Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m"))
    t.TagConfigure("c", Justify("center"))
    t.TagConfigure("e", Offset("-2p"))
    t.TagConfigure("t", Font("times", fontSize))
    sym := " <t>T<e>E</e>X</t> "
    tex := `$Q(\xi) = \lambda_1 y_1^2 \sum_{i=2}^n \sum_{j=2}^n y_i b_{ij} y_j$`
    t.InsertML(`<c>Hello Go + Tk`, NewPhoto(Data(icon)), Padx("4p"), `users!
<br><br>Hello Go + Tk +`, sym, tex, ` users! (\$inline math\$)
<br><br>Hello Go + Tk +`, sym, `$`+tex+`$`, ` users! (\$\$display math\$\$)</c>
<br><br>The above exemplifies embeding pictures and`, sym, `scripts. A text widget can also embed other widgets. For example,
when a`, Button(font, Txt("<Tbutton>")), Padx("4p"), Pady("2p"), Align("center"), `and
a`, Entry(font, Textvariable("<TEntry>"), Background(White), Width(8)), Padx("4p"), Pady("2p"), Align("center"), `are part of
the markup, they will reflow when their containing text widget is resized.`)
    App.Center().Wait()
}

embed.png

embed2.png

示例12 按钮

package main

import _ "embed"
import . "modernc.org/tk9.0"

//go:embed red_corner.png
var red []byte

//go:embed green_corner.png
var green []byte

func main() {
    StyleThemeUse("default")
    StyleElementCreate("Red.Corner.TButton.indicator", "image", NewPhoto(Data(red)))
    StyleElementCreate("Green.Corner.TButton.indicator", "image", NewPhoto(Data(green)))
    StyleLayout("Red.Corner.TButton",
        "Button.border", Sticky("nswe"), Border(1), Children(
            "Button.focus", Sticky("nswe"), Children(
                "Button.padding", Sticky("nswe"), Children(
                    "Button.label", Sticky("nswe"),
                    "Red.Corner.TButton.indicator", Side("right"), Sticky("ne")))))
    StyleLayout("Green.Corner.TButton",
        "Button.border", Sticky("nswe"), Border(1), Children(
            "Button.focus", Sticky("nswe"), Children(
                "Button.padding", Sticky("nswe"), Children(
                    "Button.label", Sticky("nswe"),
                    "Green.Corner.TButton.indicator", Side("right"), Sticky("ne")))))
    opts := Opts{Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m")}
    rb := TButton(Txt("Red"))
    gb := TButton(Txt("Green"))
    Grid(rb, gb, opts)
    Grid(TButton(Txt("Use style"), Command(func() {
        rb.Configure(Style("Red.Corner.TButton"))
        gb.Configure(Style("Green.Corner.TButton"))
    })), TExit(), opts)
    App.Wait()
}

tbutton.png

示例13. 类似 Bootstrap 5 的主题按钮

package main

import (
    . "modernc.org/tk9.0"
    "modernc.org/tk9.0/b5"
)

func main() {
    background := White
    primary := b5.Colors{b5.ButtonText: "#fff", b5.ButtonFace: "#0d6efd", b5.ButtonFocus: "#98c1fe"}
    secondary := b5.Colors{b5.ButtonText: "#fff", b5.ButtonFace: "#6c757d", b5.ButtonFocus: "#c0c4c8"}
    success := b5.Colors{b5.ButtonText: "#fff", b5.ButtonFace: "#198754", b5.ButtonFocus: "#9dccb6"}
    danger := b5.Colors{b5.ButtonText: "#fff", b5.ButtonFace: "#dc3545", b5.ButtonFocus: "#f0a9b0"}
    warning := b5.Colors{b5.ButtonText: "#000", b5.ButtonFace: "#ffc107", b5.ButtonFocus: "#ecd182"}
    info := b5.Colors{b5.ButtonText: "#000", b5.ButtonFace: "#0dcaf0", b5.ButtonFocus: "#85d5e5"}
    light := b5.Colors{b5.ButtonText: "#000", b5.ButtonFace: "#f8f9fa", b5.ButtonFocus: "#e9e9ea"}
    dark := b5.Colors{b5.ButtonText: "#fff", b5.ButtonFace: "#212529", b5.ButtonFocus: "#a0a2a4"}
    link := b5.Colors{b5.ButtonText: "#1774fd", b5.ButtonFace: "#fff", b5.ButtonFocus: "#c2dbfe"}
    StyleThemeUse("default")
    opts := Opts{Padx("1m"), Pady("2m"), Ipadx("1m"), Ipady("1m")}
    Grid(TButton(Txt("Primary"), Style(b5.ButtonStyle("primary.TButton", primary, background, false))),
        TButton(Txt("Secondary"), Style(b5.ButtonStyle("secondary.TButton", secondary, background, false))),
        TButton(Txt("Success"), Style(b5.ButtonStyle("success.TButton", success, background, false))),
        opts)
    Grid(TButton(Txt("Danger"), Style(b5.ButtonStyle("danger.TButton", danger, background, false))),
        TButton(Txt("Warning"), Style(b5.ButtonStyle("warning.TButton", warning, background, false))),
        TButton(Txt("Info"), Style(b5.ButtonStyle("info.TButton", info, background, false))),
        opts)
    Grid(TButton(Txt("Light"), Style(b5.ButtonStyle("light.TButton", light, background, false))),
        TButton(Txt("Dark"), Style(b5.ButtonStyle("dark.TButton", dark, background, false))),
        TButton(Txt("Link"), Style(b5.ButtonStyle("link.TButton", link, background, false))),
        opts)
    Grid(TButton(Txt("Primary"), Style(b5.ButtonStyle("focused.primary.TButton", primary, background, true))),
        TButton(Txt("Secondary"), Style(b5.ButtonStyle("focused.secondary.TButton", secondary, background, true))),
        TButton(Txt("Success"), Style(b5.ButtonStyle("focused.success.TButton", success, background, true))),
        opts)
    Grid(TButton(Txt("Danger"), Style(b5.ButtonStyle("focused.danger.TButton", danger, background, true))),
        TButton(Txt("Warning"), Style(b5.ButtonStyle("focused.warning.TButton", warning, background, true))),
        TButton(Txt("Info"), Style(b5.ButtonStyle("focused.info.TButton", info, background, true))),
        opts)
    Grid(TButton(Txt("Light"), Style(b5.ButtonStyle("focused.light.TButton", light, background, true))),
        TButton(Txt("Dark"), Style(b5.ButtonStyle("focused.dark.TButton", dark, background, true))),
        TButton(Txt("Link"), Style(b5.ButtonStyle("focused.link.TButton", link, background, true))),
        opts)
    Grid(TExit(), Columnspan(3), opts)
    App.Configure(Background(background)).Wait()
}

b5.png


不同系统下的效果展示
macOS下的效果
darwin.png

FreeBSD Xfce4
freebsd.png

Linux Mate 1.26.0
linux.png

Windows 11
windows11.png

标签: Go

相关文章

从入门到放弃:使用 spf13/viper 管理 Go 应用配置

在现代软件开发中,配置管理是一个至关重要的环节。随着应用的复杂性增加,配置管理的需求也变得更加多样化和复杂化。Go 语言社区中,spf13/viper 是一个非常流行的配置管理库,它提供了一种强...

使用 spf13/cobra 构建强大的 Go 命令行应用

spf13/cobra 是 Go 语言中非常流行的一个库,用于创建命令行应用(CLI)。它提供了一种强大且易于使用的框架来开发支持复杂命令结构的应用程序。Cobra 库主要用于创建像 kubec...

Go语言Web框架 Fiber入门教程

Fiber 是一个基于 Go 语言的 Web 框架,灵感来源于 Express.js,旨在提供快速、简单且轻量级的开发体验。Fiber 的设计目标是让开发者能够快速构建高性能的 Web 应用,同...

基于Go语言开源免费轻量级网站防火墙SamWaf

SamWaf网站防火墙是一款适用于小公司、工作室和个人网站的免费轻量级网站防火墙,完全私有化部署,数据加密且仅保存本地,一键启动,支持Linux,Windows 64位主要功能:完全独立引擎,防...

如何实现让我们部署的Go应用在进程挂掉之后自动重启

在软件开发和部署过程中,确保应用的高可用性是至关重要的。对于使用Go语言开发的应用来说,实现在进程异常终止后自动重启是提高服务稳定性的有效策略之一。下面将围绕如何实现Go应用在挂掉之后自动重启进...

图片Base64编码

CSR生成

图片无损放大

图片占位符

Excel拆分文件