You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Golang检测网络连接是否为按流量计费类型?

检测按流量计费的网络连接(Golang实现)

核心思路

按流量计费的网络标记(Metered Connection)是系统层面的属性,Golang本身没有原生跨平台API,需要通过调用各系统的底层接口或工具来实现。以下分平台给出可行方案:


Linux 平台

Linux下通常由NetworkManager管理网络是否为按流量计费状态,可通过netlink接口或解析系统命令获取:

方法1:使用netlink库(推荐)

借助第三方库github.com/vishvananda/netlink直接获取网络接口的Metered属性:

package main

import (
	"fmt"
	"github.com/vishvananda/netlink"
)

func main() {
	links, err := netlink.LinkList()
	if err != nil {
		fmt.Printf("获取网络接口失败: %v\n", err)
		return
	}

	for _, link := range links {
		attrs, err := link.Attrs()
		if err != nil {
			continue
		}
		// 检查是否为按流量计费
		if attrs.Metered == netlink.METERED_YES {
			fmt.Printf("接口 %s 是按流量计费的\n", attrs.Name)
		} else if attrs.Metered == netlink.METERED_NO {
			fmt.Printf("接口 %s 不是按流量计费的\n", attrs.Name)
		} else {
			fmt.Printf("接口 %s 的流量计费状态未知\n", attrs.Name)
		}
	}
}

方法2:执行系统命令(无需第三方库)

通过nmcli命令查询当前活跃连接的Metered状态:

package main

import (
	"fmt"
	"os/exec"
	"strings"
)

func main() {
	cmd := exec.Command("nmcli", "-t", "-f", "NAME,METERED", "connection", "show", "--active")
	output, err := cmd.Output()
	if err != nil {
		fmt.Printf("执行命令失败: %v\n", err)
		return
	}

	lines := strings.Split(string(output), "\n")
	for _, line := range lines {
		if line == "" {
			continue
		}
		parts := strings.Split(line, ":")
		if len(parts) != 2 {
			continue
		}
		connName := parts[0]
		metered := parts[1]
		if metered == "yes" {
			fmt.Printf("连接 %s 是按流量计费的\n", connName)
		} else {
			fmt.Printf("连接 %s 不是按流量计费的\n", connName)
		}
	}
}

Windows 平台

Windows可通过Network List Manager API获取网络连接的IsMetered属性,借助go-ole库实现:

package main

import (
	"fmt"
	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

func main() {
	err := ole.CoInitialize(0)
	if err != nil {
		fmt.Printf("初始化COM环境失败: %v\n", err)
		return
	}
	defer ole.CoUninitialize()

	networkListManager, err := oleutil.CreateObject("NetworkListManager")
	if err != nil {
		fmt.Printf("创建NetworkListManager对象失败: %v\n", err)
		return
	}
	defer networkListManager.Release()

	nlmDispatch, err := networkListManager.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		fmt.Printf("获取IDispatch接口失败: %v\n", err)
		return
	}
	defer nlmDispatch.Release()

	networksProp, err := oleutil.GetProperty(nlmDispatch, "Networks")
	if err != nil {
		fmt.Printf("获取Networks集合失败: %v\n", err)
		return
	}
	defer networksProp.Clear()

	networkEnum, err := networksProp.ToIDispatch().QueryInterface(ole.IID_IEnumVARIANT)
	if err != nil {
		fmt.Printf("获取枚举器失败: %v\n", err)
		return
	}
	defer networkEnum.Release()

	var variant ole.VARIANT
	for {
		fetched, err := networkEnum.Next(1, &variant, nil)
		if err != nil || fetched == 0 {
			break
		}

		networkDispatch := variant.ToIDispatch()
		name, _ := oleutil.GetProperty(networkDispatch, "Name")
		isMetered, _ := oleutil.GetProperty(networkDispatch, "IsMetered")

		if isMetered.Value().(bool) {
			fmt.Printf("网络 %s 是按流量计费的\n", name.Value())
		} else {
			fmt.Printf("网络 %s 不是按流量计费的\n", name.Value())
		}

		variant.Clear()
	}
}

macOS 平台

macOS通过SystemConfiguration框架获取网络配置,使用cgo调用系统API:

package main

/*
#cgo LDFLAGS: -framework SystemConfiguration
#include <SystemConfiguration/SystemConfiguration.h>
#include <stdbool.h>

bool isNetworkMetered() {
    bool isMetered = false;
    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, "MeteredCheck", NULL, NULL);
    if (store) {
        CFPropertyListRef config = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));
        if (config) {
            CFDictionaryRef dict = (CFDictionaryRef)config;
            CFNumberRef type = CFDictionaryGetValue(dict, CFSTR("ConnectionType"));
            if (type) {
                int connType;
                CFNumberGetValue(type, kCFNumberIntType, &connType);
                // kSCNetworkConnectionTypeMetered 对应值为4
                if (connType == 4) {
                    isMetered = true;
                }
            }
            CFRelease(config);
        }
        CFRelease(store);
    }
    return isMetered;
}
*/
import "C"
import "fmt"

func main() {
	if C.isNetworkMetered() {
		fmt.Println("当前网络是按流量计费的")
	} else {
		fmt.Println("当前网络不是按流量计费的")
	}
}

注意事项

  • 跨平台项目可通过runtime.GOOS判断当前系统,分支执行对应平台的代码
  • 部分方法需要管理员权限(如Linux下访问netlink接口、Windows下调用COM接口)
  • 系统工具(如nmcli)可能并非所有Linux发行版都预装,需提前确认依赖

内容的提问来源于stack exchange,提问作者OldLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:40:29