Golang新手入门问题求助

Golang新手入门问题求助 我是这里的新手。我所有的应用程序都是用AutoHotkey编写的,但经常需要一些只能在Windows上运行的小工具,由于AHK可执行文件太大(至少500KB),需要用其他语言编写。到目前为止,我尝试过的编程语言都存在缺乏Unicode支持的大问题。所以最终来到这里,主要是因为了解到Go语言原生支持Unicode。

这里有友好的专家能告诉我Go是否适合我吗?比如我现在就需要一个小型启动器程序,它需要完成以下功能:

  • 需要获取启动时指定的命令行参数: Launcher.exe “参数1” “参数2” …
  • 将二进制文件的内容读取为字节字符串
  • 使用之前获取的命令行参数启动可执行文件
  • 注意:参数和可执行文件名可能包含Unicode字符!

我的问题是:对于新手来说,用Go实现这些是否足够简单?这样的工具能小于50KB吗?有人能帮我草拟一个启动器的简短示例代码作为入门参考吗?

诚挚地, Z.

附言:我已经安装好Go并成功运行了hello.go测试…

func main() {
    fmt.Println("hello world")
}

更多关于Golang新手入门问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html

15 回复

兆字节——真的吗?

PowerShell:我需要一个可执行文件……

更多关于Golang新手入门问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


非常感谢,johandalabacka!

是的,我知道这些方法(PS2Exe),但这涉及到依赖项(PowerShell、.NET),在我的情况下应该避免这些依赖…

谢谢你,NobbZ!

当然,但这只是一个非常概括的看法。在Freebasic中,我的可执行文件大约只有50kB,而且没有任何依赖项。(遗憾的是Unicode支持非常差…)

如果文件大小是个问题,那么 Go 可能不适合你。编译后的可执行文件大小会达到几兆字节。

如果你只需要在 Windows 上运行,或许学习 PowerShell 会更好。它已经内置在所有最新版本的 Windows 中,并且你可以调用任何系统函数。程序的大小将只是脚本的大小。

要么你希望生成小巧的二进制文件/脚本,但需要安装其依赖项/运行时环境;要么你希望获得自包含的二进制文件,但这些文件体积会迅速变得相当庞大。

感谢NobbZ,感谢您为帮助我付出的努力。

这不应是理论层面的讨论。我目前使用的启动器是用Freebasic编写的,其大小为57 kB,并且绝对是一个独立的应用程序(这意味着它不依赖于Freebasic或.NET的任何未编译组件)。

感谢NobbZ的解释。根据我所知,FB没有这样的依赖项。如果使用了Windows函数,这是通过"#include once windows.bi"来实现的,以便访问kernel32.dll,该文件是每个Windows版本和安装的一部分。

感谢大家的帮助。Go的Unicode支持将会很棒,但是…

NobbZ,我不理解你为何要让人觉得追求小体积可执行文件的想法很奇怪,但也许你可以考虑到一个小插件不应该比实际应用程序更大,而且在某些情况下体积确实很重要。不过……关于这一点该说的都已经说了。

是的,我理解 Go 语言不符合我的需求。

也许你可以向我解释一下,当提到"全新 Windows 安装"与"预装 Windows"时,你所说的隐藏依赖是什么意思?

是的,Go语言会静态链接所有内容,特别是其运行时(垃圾回收器、标准库等)。

一个简单的hello world程序会生成1.9 MB的可执行文件,通过应用strip命令可以减小约0.6 MB,最终缩小到1.3 MB。

这是在Linux机器上的测试结果,我手头没有Windows工作站进行测试。

此示例使用的代码:

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

你能在全新的Windows安装上运行这个程序吗?不是在预装了大量臃肿软件的Windows上,而是在没有任何额外软件的真正全新Windows安装上?

无论如何,你为什么认为实际的二进制文件大小很重要?在大多数现代系统上,这其实并不重要。除非你做嵌入式开发,否则我怀疑文件大小是个值得关注的问题。

但如果你唯一想做的就是自动化系统的某些方面,请坚持使用PowerShell或Windows脚本宿主

我们可能已经告诉过你,但如果文件大小确实是你关心的问题,那么Go不是你的首选语言。

将PowerShell脚本转换为可执行文件有很多方法:

图片

使用这些工具将Ps1文件转换为.exe

Ps1文件是PowerShell脚本,用于配置各种执行策略,只能通过PowerShell执行。简单来说,PowerShell是…

我还没有使用过任何这些工具,所以无法提供任何推荐。刚刚测试了http://www.f2ko.de/en/op2e.php,创建了一个helloworld脚本并将其编译为17kB大小的exe文件。

正如我所说,我讨论的是运行时环境。对于 .Net 而言显然是 CLR,它自 Windows 8.0 甚至 Windows 7 起就预装在每个 Windows 系统中,并且通过 Windows 更新自动升级。

FreeBasic 同样具备运行时环境,它可能依赖其他库文件——这些库可能是基础系统的组成部分,也可能不是。由于我未使用 Windows 系统且无意使用,无法提供更多信息。您可以通过 dependency walker 查看程序引用的 DLL 文件,这至少是我通过谷歌搜索找到的首选方案。

从用户角度而言,我自然更倾向于 20 个可执行文件共享同一个运行时环境,而非每个可执行文件都反复打包相同代码。但另一方面,作为需要面向无法控制库安装的系统进行开发的程序员,Go 语言显得尤为可贵,因为我知道它能在目标系统上开箱即用……

Zvonko:

在Freebasic中,我的可执行文件大约为50 kB,并且没有依赖项。

根据谷歌搜索,如果你要使用字符串和数组,至少需要一个Free Basic运行时环境…

而且Print "Hello, World!"编译生成的二进制文件会动态链接到libclibmlibpthreadlibcursesw等库。libpthread大小为150k,libm为1.6M,libc还有2.1M。需要我继续查libcurses的大小吗?

我不确定Windows系统是否也有类似ldd这样的工具,但请相信,你确实存在依赖项。在Linux系统上这些库通常都存在,但我仍不会声称"没有依赖项",因为有些Linux系统明确不使用libc而用libmusl替代。针对这些平台你需要重新编译。

PowerShell 和 .Net 是任何版本 Windows 10 的组成部分,因此您无需下载任何内容。

网站图标

亚伦·斯特布纳的网络日志

邮件问答:各版本操作系统中包含的 .NET Framework 版本对应关系

问题:我最近安装了 Windows Vista。当查看"程序和功能"(原"添加/删除程序")控制面板时,没有看到列出的 .NET Framework 2.0。因此我决定通过…

以下是针对你需求的Go语言实现方案,完全满足Unicode支持和轻量化要求。

示例代码:

package main

import (
	"io"
	"os"
	"os/exec"
)

func main() {
	// 获取命令行参数(自动支持Unicode)
	args := os.Args[1:]
	if len(args) < 1 {
		os.Exit(1)
	}

	// 读取当前可执行文件内容
	exePath, err := os.Executable()
	if err != nil {
		os.Exit(1)
	}

	file, err := os.Open(exePath)
	if err != nil {
		os.Exit(1)
	}
	defer file.Close()

	// 读取为字节切片
	content, err := io.ReadAll(file)
	if err != nil {
		os.Exit(1)
	}
	_ = content // 此处可按需处理二进制内容

	// 使用参数启动目标程序(完整Unicode支持)
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	if err := cmd.Run(); err != nil {
		os.Exit(1)
	}
}

编译命令(关键步骤):

go build -ldflags="-s -w" launcher.go

验证结果:

  • 文件大小:使用以上编译参数后,生成的可执行文件通常在 2-3MB 左右
  • 但通过 UPX 压缩后可降至约 1-1.5MB:
    upx --best launcher.exe
    

关于50KB目标的说明: Go静态编译的特性导致基础运行时约2MB,这是包含完整Unicode支持和运行时环境的代价。若必须小于50KB,建议考虑以下方案:

// 最小化版本(仅核心功能)
package main

import (
	"os"
	"os/exec"
)

func main() {
	if len(os.Args) > 1 {
		cmd := exec.Command(os.Args[1], os.Args[2:]...)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Stdin = os.Stdin
		cmd.Run()
	}
}

总结:

  • Go完全满足你的Unicode需求
  • 实现简单直观,代码可读性强
  • 标准编译约2-3MB,经UPX压缩后约1-1.5MB
  • 若50KB是硬性要求,需考虑其他语言(如C+MinGW)或接受Go的运行时大小

这个启动器示例可直接编译使用,参数传递和Unicode处理都是自动支持的。

回到顶部