LoginSignup
0

More than 3 years have passed since last update.

golangで[]byte(uint8)をfloat64にconvertする方法

Last updated at Posted at 2019-07-25

TL;DR

コメントいただいた方法でアップデートしました!
とりあえずこうしてみたけど、もっといいやり方ありそうなので、有識者な方教えてください。

f := *(*float64)(unsafe.Pointer(&out[0]))

モチベーションと背景

Prometheusを使ったサーバリソースモニタの環境整備を進めており、既存exporterでカバーできないMetricsが欲しくなったのでexporterを自作してみることにしました。
golang自体がまったく初めてで、先週末に初めてhello worldしてみたところです。

exporterを作成するにあたりいくつかの言語でフォーマットやライブラリがありましたが、どうせならgolangでやってみようと思い入門し、公式のチュートリアルを一通りやってから、参考にした記事を見つつexporterを作成してみました。
成果物は コチラ

Metrics取得にbashコマンドを利用

golangでの低レイヤの情報取得は別の機会に学習しようと思い、LinuxサーバのMetrics取得についてはbashのコマンドを使いました。
参考記事:
Golangで外部コマンドを実行する方法まとめ
Goで外部コマンドをパイプして実行する
golang で UNIX コマンドパイプラインを扱う(Big Sky)

最終的には、mattnさんが公開されている go-pipeline を使って、UNIXコマンドのパイプ処理を書きました。

go-pipeline の戻り値が []byte

bashコマンドを実行できたのはよいものの、その戻り値が []byte(uint8) で返ってくることがわかりました。
exporterの出力には、数値をfloat64で渡さないといけないらしく、[]byteからfloat64へのconvertが必要になりました。

[]byte から float64 への convert 方法

とりあえずざざざっとググってみると、
Convert byte array “[]uint8” to float64 in GoLang(StackOverFlow)
Convert a byte array to float64(StackOverFlow)
というStackOverFlowの記事があり、どうやらなんかライブラリとか関数一発でできなくて、バイナリ列をどうにかこうにかしてる模様、、ええあまりしたくないなぁ。

ライブラリでいうと、 strconv を使うのが近そうというのがわかりました。
試行錯誤した結果、[]byte を一度stringにして、その際にできてしまう末尾の \n をchompして、得られたstringをstrconvでfloat64にParseすることで、対応できました。が、ほんとにこれだけのためにこんないろいろしなきゃいけないの?というのはちょっと懐疑的。。

example.go
package main

import (
    //  "fmt"
    "flag"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    "log"
    "net/http"

    "github.com/mattn/go-pipeline" // go-pipeline : https://github.com/mattn/go-pipeline
    "strconv"
    "strings"
    "unsafe"
)

~~ 中略 ~~

func get443Estab() float64 {
    out, err := pipeline.Output(
        []string{"netstat", "-n"},
        []string{"grep", "ESTABLISHED"},
        []string{"grep", ":443"},
        []string{"wc", "-l"},
    )
    if err != nil {
        // PIPESTATUSの中に一つでも0以外が含まれると err : exit status ${status} になるので注意
        return float64(0)
    }
    f, err := strconv.ParseFloat(strings.TrimRight(*(*string)(unsafe.Pointer(&out)), "\n"), 64)
    if err != nil {
        return float64(0)
    }
    return float64(f)
}

~~  ~~

もっといいやり方あったら、教えてください m(_ _)m

versionなど

 # go version
go version go1.10.4 linux/amd64

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0