惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AI
AI
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
Scott Helme
Scott Helme
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
博客园 - 叶小钗
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
N
News and Events Feed by Topic
Cloudbric
Cloudbric
B
Blog
Cisco Talos Blog
Cisco Talos Blog
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
V
Visual Studio Blog
A
Arctic Wolf
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
S
Security @ Cisco Blogs
博客园 - 聂微东
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Y
Y Combinator Blog
G
GRAHAM CLULEY
L
LINUX DO - 热门话题
量子位
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Troy Hunt's Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tenable Blog
月光博客
月光博客
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
D
Docker
www.infosecurity-magazine.com
www.infosecurity-magazine.com
雷峰网
雷峰网
博客园 - 司徒正美
T
The Exploit Database - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
Help Net Security
Help Net Security
D
DataBreaches.Net

kmcd.dev

gRPC-Web Should Have Fixed gRPC Making Dynamic Protobuf Fast in Go Proxy, Record, and Mock gRPC APIs with FauxRPC Exploring Protocol Buffers Interactively Introducing ProtoDocs Ghost in the Shell: The Manga Behind the Anime The Hidden Cost of google.protobuf.Value Why Networking Built Its Own Data Modeling Language Zero-Friction Demos with WASM Let's Learn About BGP ConnectRPC: Where is it now? Building APIs with Contracts The Case for Greppable Code Unknown Fields in Protobuf IRC Log: Reactionary Y'all are Sleeping on Mise-en-Place IRC Log: Standup 2 HTTP/2 From Scratch: Part 4 IRC Log: rm -rf /var/opt/gitlab/postgresql/data HTTP/2 From Scratch: Part 3 Building a Live BGP Map HTTP/2 From Scratch: Part 2 IRC Log: The Cloud Scale Incident Visualizing the Internet (2026) Shell Log: Namaste HTTP/2 From Scratch: Part 1 IRC Log: Standup HTTP/1.1 From Scratch WHOIS is dead, long live RDAP Months Considered Harmful Encryption vs. Compression On Creating My Own Cover Art Traceroute Tool from Scratch in Go My Favorite Interview Question From JSON to Protobuf Breaking gRPC Morse Code Can You Hack a Phone with Your Voice? Visualizing the Internet (2025) HTTP QUERY and Go I made a daily word game Protovalidate: Can Input Validation Be This Easy? Behold! The Barcode Scanner Mixing CEL and Protobuf for Fun FauxRPC and Protovalidate The Call of the Monolithic Codebase FauxRPC + Test Containers Self-Documenting Connect Services gRPC Over HTTP/3: Followup JSON to Protobuf Conversion gRPC: The Ugly Parts Working with Protobuf in 2024 Introducing FauxRPC HTTP/1.0 From Scratch Y'all are sleeping on HTTP/3 HTTP/0.9 From Scratch What version of HTTP are you using? Texans in Denmark gRPC Over HTTP/3 gRPC: The Good Parts Leaving Texas for Greener Pastures gRPC: The Bad Parts Unit Testing ConnectRPC Servers Daily Prompts Adding chart.js to Hugo Why I'm Rebranding Benchmarking gRPC (golang) Blog Update gRPC From Scratch: Part 3 - Protobuf Encoding Tracking the Wins Visualizing the Internet (2024) Dropping Unknown Fields in ConnectRPC RESTless: Web APIs After REST Introducing unknownconnect-go Making gRPC more approachable with ConnectRPC Inspecting Protobuf Messages Introducing protoc-gen-connect-openapi gRPC From Scratch: Part 2 - Server gRPC From Scratch: Part 1 - Client Why you should use gNMI over SNMP in 2026 The Rollercoaster of Productivity in Side Projects Lessons from a Decades-Long Project How I learned to code Economists with (virtual) Guns Visualizing the Internet (2023) softlayer-python: language bindings/CLI for a cloud company SwFTP: SFTP/FTP Server For Openstack Swift Video: Morning Copenhagen Commute Goodbye Evepraisal Visualizing the spectrum of the sun (Part 2) Visualizing the Internet (2022) Evepraisal: A price estimation tool for Eve Online Visualizing the spectrum of the sun
Faking protobuf data in Go
2026-03-26 · via kmcd.dev

If you build Go services that use protobuf over gRPC, you often need realistic-looking data. Sometimes you need a lot of it and your creative juices and manual data entry only goes so far. Tests, local demos, and stubs all benefit from messages that look plausible without carrying meaning.

FauxRPC addresses this. It’s a small Go library that fills protobuf messages with plausible data. The focus is not perfect realism; it’s speed, convenience, and reducing boilerplate.

This article covers two main use cases: populating generated protobuf types and working with dynamic descriptors. Along the way, you’ll see how to generate data and control its behavior for repeatable results.

Core entry points

FauxRPC provides two primary functions:

  • fauxrpc.SetDataOnMessage: Populates a concrete Go struct generated from .proto files.
  • fauxrpc.NewMessage: Creates a message from a protoreflect.MessageDescriptor, useful when types aren’t known at compile time.

Both use the same underlying logic; the difference is whether you start with a Go struct or a descriptor.

Filling a generated message

For a simple case, consider the Eliza demo service and its SayResponse message.

Eliza Service SayResponse Example (click to expand)View on GitHub
package main

import (
	"fmt"
	"log"

	elizav1 "buf.build/gen/go/connectrpc/eliza/protocolbuffers/go/connectrpc/eliza/v1"
	"github.com/sudorandom/fauxrpc"
	"google.golang.org/protobuf/encoding/protojson"
)

func main() {
	msg := &elizav1.SayResponse{}
	if err := fauxrpc.SetDataOnMessage(msg, fauxrpc.GenOptions{}); err != nil {
		log.Fatalf("err: %s", err)
	}
	b, err := protojson.MarshalOptions{Indent: "  "}.Marshal(msg)
	if err != nil {
		log.Fatalf("err: %s", err)
	}
	fmt.Println(string(b))
}

SetDataOnMessage mutates the message in place. Every field receives a value compatible with its type.

Marshaling to JSON produces something like:

{
  "sentence": "Jean shorts."
}

Values change each run. That randomness exposes assumptions in tests and ensures your code doesn’t rely on fixed values.

Populating a nested message

Most protobufs are more complex than a single field. For example, an ownerv1.Owner message with nested messages, timestamps, enums, and strings:

Owner Service Owner Example (click to expand)View on GitHub
package main

import (
	"fmt"
	"log"

	ownerv1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/owner/v1"
	"github.com/sudorandom/fauxrpc"
	"google.golang.org/protobuf/encoding/protojson"
)

func main() {
		msg := &ownerv1.Owner{}
		if err := fauxrpc.SetDataOnMessage(msg, fauxrpc.GenOptions{}); err != nil {
			log.Fatalf("err: %s", err)
		}
		b, err := protojson.MarshalOptions{Indent: "  "}.Marshal(msg)
		if err != nil {
			log.Fatalf("err: %s", err)
		}
		fmt.Println(string(b))
}

SetDataOnMessage recursively populates nested messages, assigns valid enum values, and generates RFC 3339 timestamps. Marshaled with protojson:

{
  "organization": {
    "id": "a4cf6166453b49d9811cfdc169c36354",
    "createTime": "1912-06-01T16:45:13.510830647Z",
    "updateTime": "2009-04-03T13:11:31.216229245Z",
    "name": "xm0r3",
    "description": "Godard selvage.",
    "url": "https://www.dynamicreintermediate.name/robust/seize/metrics/b2c",
    "verificationStatus": "ORGANIZATION_VERIFICATION_STATUS_OFFICIAL"
  }
}

This works well for local servers, demos, and tests that focus on shape rather than meaning.

Using dynamic messages

For proxies, gateways, or tools without generated Go types, dynamicpb allows message creation from descriptors. FauxRPC supports this:

Dynamic Protobuf Example (click to expand)View on GitHub
package main

import (
	"fmt"
	"log"

	elizav1 "buf.build/gen/go/connectrpc/eliza/protocolbuffers/go/connectrpc/eliza/v1"
	"github.com/sudorandom/fauxrpc"
	"google.golang.org/protobuf/encoding/protojson"
)

func main() {
    msg, err := fauxrpc.NewMessage(
        elizav1.File_connectrpc_eliza_v1_eliza_proto.Messages().ByName("SayResponse"),
        fauxrpc.GenOptions{},
    )
    if err != nil {
        log.Fatalf("err: %s", err)
    }
    b, err := protojson.MarshalOptions{Indent: "  "}.Marshal(msg)
    if err != nil {
        log.Fatalf("err: %s", err)
    }
    fmt.Println(string(b))
}

FauxRPC fills dynamic messages with the same rules as concrete types, making them usable like any other protobuf message.

Respecting protovalidate constraints

FauxRPC reads protovalidate annotations to generate data that respects field constraints. Length limits, numeric ranges, regex patterns, and formats are applied when generating values.

For example, a User message with a username, email, and age:

Protovalidate-aware Data Generation (click to expand)View on GitHub
package main

import (
	"fmt"

	"github.com/sudorandom/fauxrpc"
	gen "github.com/sudorandom/kmcd.dev/faking-protobuf-data-in-go/gen"
	"google.golang.org/protobuf/encoding/protojson"
)

func main() {
	user := &gen.User{}

	err := fauxrpc.SetDataOnMessage(user, fauxrpc.GenOptions{})
	if err != nil {
		panic(err)
	}

	out, err := protojson.MarshalOptions{Indent: "  "}.Marshal(user)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(out))
}

Sample output:

FauxRPC ensures string lengths, numeric ranges, and formats match the annotations. The result is still fake data but plausible enough to exercise validators and gateways realistically.

Controlling randomness with GenOptions

By default, FauxRPC uses a global random generator. GenOptions allows supplying a seeded gofakeit.Faker for repeatable output:

Customizing Data Generation with GenOptions (click to expand)View on GitHub
package main

import (
	"fmt"
	"log"

	"github.com/brianvoe/gofakeit/v7"
	elizav1 "buf.build/gen/go/connectrpc/eliza/protocolbuffers/go/connectrpc/eliza/v1"
	"github.com/sudorandom/fauxrpc"
	"google.golang.org/protobuf/encoding/protojson"
)

func main() {
	faker := gofakeit.New(123) // Seed the faker for deterministic output
	msg := &elizav1.SayResponse{}
	if err := fauxrpc.SetDataOnMessage(msg, fauxrpc.GenOptions{Faker: faker}); err != nil {
		log.Fatalf("err: %s", err)
	}
	b, err := protojson.MarshalOptions{Indent: "  "}.Marshal(msg)
	if err != nil {
		log.Fatalf("err: %s", err)
	}
	fmt.Println(string(b))
}

Repeatable generation helps make tests predictable without hard-coded fixtures.

FauxRPC in handlers

At the edge of a service, handlers can generate fake responses quickly.

ConnectRPC example:

ConnectRPC Handler (click to expand)View on GitHub
package main

import (
	"context"
	"github.com/sudorandom/fauxrpc"
	"github.com/bufbuild/connect-go"
	elizav1 "buf.build/gen/go/connectrpc/eliza/protocolbuffers/go/connectrpc/eliza/v1"
)

func Say(ctx context.Context, req *connect.Request[elizav1.SayRequest]) (*connect.Response[elizav1.SayResponse], error) {
    msg := &elizav1.SayResponse{}
    if err := fauxrpc.SetDataOnMessage(msg, fauxrpc.GenOptions{}); err != nil {
        return nil, err
    }
    return connect.NewResponse(msg), nil
}

Request example:

$ buf curl --schema=buf.build/connectrpc/eliza \
         -d '{"sentence": "Hello world!"}' \
         http://127.0.0.1:6660/connectrpc.eliza.v1.ElizaService/Say
{
  "sentence": "Microdosing."
}

gRPC-go example:

gRPC-go Handler (click to expand)View on GitHub
package main

import (
	"context"
	"github.com/sudorandom/fauxrpc"
	elizav1 "buf.build/gen/go/connectrpc/eliza/protocolbuffers/go/connectrpc/eliza/v1"
)

func Say(ctx context.Context, req *elizav1.SayRequest) (*elizav1.SayResponse, error) {
	msg := &elizav1.SayResponse{}
	if err := fauxrpc.SetDataOnMessage(msg, fauxrpc.GenOptions{}); err != nil {
		return nil, err
	}
	return msg, nil
}

The behavior is identical and works out-of-the-box.

FauxRPC CLI

The CLI can generate data without compiling Go code:

$ fauxrpc generate --schema=. --target=example.v1.User
{"username":"Birdie", "email":"[email protected]", "age":54}

The CLI is incredibly flexible with the –schema flag. You can point it at:

  • A local .proto file or a directory of them.
  • A compiled protobuf descriptor set (binpb).
  • A remote Buf Schema Registry repository (e.g., buf.build/acme/auth).

Closing thoughts

FauxRPC is not a data modeling tool; it generates values consistent with protobuf types and constraints. This makes it useful for quickly standing up services, testing clients, and exploring API shapes.

It works with both ConnectRPC and grpc-go, and provides hooks for custom data generation. For full details, see the pkg.go.dev reference.