Golang在物联网(IoT)中的应用探索
Golang在物联网(IoT)中的应用探索 各位,Go语言可以用于物联网设备编程吗? 主要编程需求是:
能够连接多个设备 能够存储数据 应支持 [Arduino] 或 [Raspberry Pi] 运行速度应相当快
Go语言在物联网编程中可靠吗?
根据我有限的经验,树莓派并不可靠。可以看看UP Board。价格稍高,但它们是经过Linux内核优化的稳定产品。
还有专为这类用例设计的 TinyGo:https://tinygo.org/
你可以在多种不同的微控制器开发板上编译并运行 TinyGo 程序,例如 BBC micro:bit 和 Arduino Uno。
只要在支持的平台(微处理器)上运行Go程序,就没有问题。
对于Arduino来说,这不可行,因为Go是专门为计算而设计的。最好还是坚持使用C/C++。如果你想在嵌入式级别获得Go支持,可以考虑为开发团队做出贡献。
对于树莓派,你需要记住像这样交叉编译你的程序:
$ env GOOS=linux GOARCH=arm GOARM=5 go build <path/to/program>
Go在边缘数据处理和后端服务器方面是可靠的。对于传感器/执行器接口,根据你的设计,微控制器汇编 / C / C++ 会更合适。
Sujith-sunny:
编程的主要需求是:
能够连接多种设备 能够存储数据 应支持 [Arduino] 或 [Raspberry Pi] 速度应相当快 Go 语言对于物联网编程可靠吗?
绝对可靠。我用 Go 语言编写了一个 SCADA IIoT 系统(实时监控和命令),得益于 goroutines,能够实时连接到许多设备。我还在 Raspberry Pi 上工作过(参见此处了解方法)。是的,它非常快速和可靠。
hollowaykeanho:
你可以考虑为团队进行开发。
bklimczak:
还有 TinyGo。
抱歉有一些打字错误。感谢你的支持 @bklimczak。 🙂
我原本想表达的是“你可以帮助开发团队在嵌入式微控制器上启用 Go”。根据我对 TinyGo 的测试,你必须遵守一些规则:
- 避免堆内存分配(堆分配 | TinyGo)
- 目前不支持
map类型(Go 语言特性 | TinyGo)
考虑到从互联网导入 Go 包的便利性,你在导入 Go 包时必须非常、非常小心,因为很多包内部都使用了 map 数据类型。大多数时候,编程体验就像踮着脚尖走路。在我看来,这相当费力,这就是为什么我(目前)不推荐在微控制器上使用 Go。
如果你能解决这些难题并为开发团队(例如 TinyGo / Go 开发团队)做出贡献,我相信整个 Go 社区都会感谢你的努力。 🙂
如果你需要小型板卡,但由于某些原因必须严格使用 Go,你可以考虑那些非常小的单板计算机,这样你就不需要处处受限了:
- 购买 Compute Module 3+ – Raspberry Pi
- https://www.friendlyarm.com/index.php?route=product/product&product_id=132
探索愉快。
Go语言非常适合物联网(IoT)开发,特别是对于需要并发连接、高效数据处理和跨平台部署的场景。以下是具体实现示例:
1. 多设备连接(使用goroutine和channel)
package main
import (
"fmt"
"net"
"sync"
"time"
)
type DeviceManager struct {
devices map[string]net.Conn
mu sync.RWMutex
dataCh chan DeviceData
}
type DeviceData struct {
ID string
Data []byte
}
func (dm *DeviceManager) HandleDevice(conn net.Conn, deviceID string) {
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
if err != nil {
fmt.Printf("Device %s disconnected\n", deviceID)
dm.mu.Lock()
delete(dm.devices, deviceID)
dm.mu.Unlock()
return
}
dm.dataCh <- DeviceData{
ID: deviceID,
Data: buffer[:n],
}
}
}
func (dm *DeviceManager) StartServer(port string) {
ln, _ := net.Listen("tcp", ":"+port)
defer ln.Close()
for {
conn, _ := ln.Accept()
deviceID := fmt.Sprintf("device_%d", time.Now().UnixNano())
dm.mu.Lock()
dm.devices[deviceID] = conn
dm.mu.Unlock()
go dm.HandleDevice(conn, deviceID)
}
}
2. 数据存储(使用SQLite)
package main
import (
"database/sql"
"log"
"time"
_ "github.com/mattn/go-sqlite3"
)
type DataStore struct {
db *sql.DB
}
func NewDataStore(dbPath string) (*DataStore, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
// 创建设备数据表
createTable := `
CREATE TABLE IF NOT EXISTS device_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
data BLOB,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)`
_, err = db.Exec(createTable)
if err != nil {
return nil, err
}
return &DataStore{db: db}, nil
}
func (ds *DataStore) SaveData(deviceID string, data []byte) error {
_, err := ds.db.Exec(
"INSERT INTO device_data (device_id, data) VALUES (?, ?)",
deviceID, data,
)
return err
}
func (ds *DataStore) GetRecentData(deviceID string, limit int) ([]DeviceData, error) {
rows, err := ds.db.Query(
"SELECT data, timestamp FROM device_data WHERE device_id = ? ORDER BY timestamp DESC LIMIT ?",
deviceID, limit,
)
if err != nil {
return nil, err
}
defer rows.Close()
var results []DeviceData
for rows.Next() {
var data []byte
var timestamp time.Time
if err := rows.Scan(&data, ×tamp); err != nil {
return nil, err
}
results = append(results, DeviceData{
ID: deviceID,
Data: data,
})
}
return results, nil
}
3. Raspberry Pi GPIO控制
package main
import (
"fmt"
"time"
"github.com/stianeikeland/go-rpio/v4"
)
func ControlGPIO() {
// 初始化GPIO
err := rpio.Open()
if err != nil {
fmt.Println("Failed to open GPIO:", err)
return
}
defer rpio.Close()
// 设置引脚17为输出模式
pin := rpio.Pin(17)
pin.Output()
// 控制LED闪烁
for i := 0; i < 10; i++ {
pin.High() // 打开
time.Sleep(500 * time.Millisecond)
pin.Low() // 关闭
time.Sleep(500 * time.Millisecond)
}
}
4. 完整的IoT设备示例
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
)
type SensorData struct {
DeviceID string `json:"device_id"`
Temperature float64 `json:"temperature"`
Humidity float64 `json:"humidity"`
Timestamp int64 `json:"timestamp"`
}
type IoTDevice struct {
ID string
dataCh chan SensorData
quitCh chan bool
}
func (d *IoTDevice) StartSensing() {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// 模拟传感器数据
data := SensorData{
DeviceID: d.ID,
Temperature: 20 + (5 * (time.Now().Unix() % 10)),
Humidity: 40 + (10 * (time.Now().Unix() % 10)),
Timestamp: time.Now().Unix(),
}
d.dataCh <- data
case <-d.quitCh:
return
}
}
}
func main() {
// 创建设备管理器
deviceManager := &DeviceManager{
devices: make(map[string]net.Conn),
dataCh: make(chan DeviceData, 100),
}
// 创建数据存储
dataStore, err := NewDataStore("./iot_data.db")
if err != nil {
log.Fatal(err)
}
// 启动HTTP API
http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
var data SensorData
json.NewDecoder(r.Body).Decode(&data)
jsonData, _ := json.Marshal(data)
dataStore.SaveData(data.DeviceID, jsonData)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
})
// 启动TCP服务器处理设备连接
go deviceManager.StartServer("8080")
// 启动数据处理器
go func() {
for deviceData := range deviceManager.dataCh {
// 处理设备数据
fmt.Printf("Received from %s: %s\n",
deviceData.ID,
string(deviceData.Data))
// 存储到数据库
dataStore.SaveData(deviceData.ID, deviceData.Data)
}
}()
// 启动HTTP服务器
log.Fatal(http.ListenAndServe(":8081", nil))
}
性能特点:
- 并发处理:goroutine轻量级,可同时处理数千设备连接
- 内存效率:垃圾回收器优化,适合资源受限的嵌入式设备
- 编译部署:单二进制文件部署,依赖少
- 跨平台:支持ARM架构(Raspberry Pi),交叉编译简单
- 标准库丰富:内置HTTP、TCP、JSON等协议支持
对于Arduino,Go可通过串口通信或使用TinyGo编译器直接编程。Raspberry Pi上Go可直接运行,通过go-rpio等库控制GPIO。Go的静态编译特性确保在IoT设备上的快速启动和稳定运行。

