gogcli 实战指南:用gog maps places search在终端里做 Google Places 文本搜索
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
本篇聚焦 gogcli(Google Workspace in your terminal)中的gog maps places search子命令:如何完成 Places API 密钥配置、如何按文本搜索地点、如何以 TSV/JSON 两种格式消费结果,并结合源码拆解命令从参数解析到 HTTP 请求的完整调用链。读完你不仅能直接复制命令用于脚本与 Agent 工作流,还能理解该命令底层调用的 Places API v1 接口形态(places:searchText、字段掩码、密钥鉴权头)与错误边界。
命令概览与别名体系
gog maps places search是 gogcli Maps 子树下的地点文本搜索命令,官方文档页 gog-maps-places-search.md 给出的标准用法为:
gog maps (map) places (place) search (find) <query> ... [flags]括号中的内容是别名:命令树在 internal/cmd/maps.go 中用 kong 标签注册,maps可写作map,places可写作place,search可写作find。也就是说下面三种写法等价:
gog maps places search "cafe in Berlin" gog map place find "cafe in Berlin"query是位置参数,且支持多段——从源码看,参数定义为Query []string,运行时用空格把所有片段拼接成一个查询串(见 MapsPlacesSearchCmd.Run),所以不必担心 shell 引号截断,gog maps places search cafe in Berlin与加引号效果一致;若拼接后为空则直接报missing query。
该命令在 Maps 子树中属于 Places 分支(docs/commands/gog-maps-places.md),与gog maps places details平级,同级的还有directions、distance、geocode、reverse-geocode(见 docs/commands/gog-maps.md 对应的 internal/cmd/maps.go 命令树定义)。完整命令索引见 docs/commands/README.md。
Places API 密钥的三种配置方式
gog maps places search使用 Google API 密钥(而非 OAuth 账号)鉴权。密钥解析入口是 placesAPIKey,其读取逻辑由 internal/config/keys.go 中的KeyPlacesAPIKey规格定义,按以下优先级取第一个非空值:
- 环境变量
GOG_PLACES_API_KEY; - 环境变量
GOOGLE_PLACES_API_KEY; - 配置文件中的
places_api_key项(通过gog config set places_api_key <key>写入,配置项在 internal/config/config.go 中映射为places_api_keyJSON 字段)。
该键被标记为Sensitive: true,即配置读写路径会对其做脱敏处理。三个来源都缺失时,命令给出明确的排障提示:
Google Maps/Places API key required. Set GOG_PLACES_API_KEY, GOOGLE_PLACES_API_KEY, or run 'gog config set places_api_key <key>'因此最省事的落地方式是:
gog config set places_api_key AIza... # 写入配置 # 或临时使用环境变量(适合 CI): GOG_PLACES_API_KEY=AIza... gog maps places search "coffee"命令参数详解
该命令自身只有两个查询参数,其余为全局通用 flag:
| 参数 | 类型 | 说明 |
|---|---|---|
<query> ... | 位置参数(多值) | 文本搜索查询串,多个片段会以空格拼接;空串直接报 usage 错误 |
--language | string | BCP-47 语言代码,作为请求体languageCode下发 |
--region | string | CLDR 地区代码,作为请求体regionCode下发,用于结果本地化偏好 |
--language与--region会经strings.TrimSpace处理后装入googleapi.PlacesLookupOptions(见 internal/cmd/maps.go),仅当非空时才写入请求,即不传时对 API 默认行为零影响。
全局常用 Flag
文档页列出的完整 Flag 表覆盖所有 gogcli 全局 flag,这里挑出与脚本化、Agent 场景最相关的几项(完整表格以 gog-maps-places-search.md 为准):
| Flag | 类型 | 默认 | 作用 |
|---|---|---|---|
-j/--json/--machine | bool | false | 以 JSON 输出到 stdout,最适合脚本消费 |
-p/--plain/--tsv | bool | false | 输出稳定可解析的 TSV 文本(无颜色) |
--select/--pick | string | JSON 模式下选取逗号分隔字段(支持点路径,尽力而为) | |
--results-only | bool | JSON 模式只输出主结果,丢弃nextPageToken等信封字段 | |
--color | string | auto | 颜色输出:auto/always/never |
-n/--dry-run等别名 | bool | 不产生变更,仅打印意图动作 | |
--no-input/--non-interactive | bool | 从不交互提问,失败即退出(CI 友好) | |
-a/--account | string | 账号邮箱、别名或auto(本命令走 API 密钥,一般用不到) | |
--access-token | string | 直接使用给定 access token(本命令不使用 OAuth) | |
--quota-project | string | 计费项目(X-Goog-User-Project) | |
--enable-commands/--disable-commands | string | 以点路径限制/禁用命令前缀,做 CLI 收窄 | |
--wrap-untrusted | bool | false | 在 JSON/raw 输出中用“外部不可信内容”标记包裹抓取到的文本字段 |
-y/--force | bool | 跳过破坏性命令确认 | |
-v/--verbose | bool | 开启详细日志 | |
--home | string | 覆盖 gogcli 配置/数据/状态/缓存根目录(等价GOG_HOME) |
输出格式:人类可读 TSV 与 JSON
输出由 writeMapsPlace 统一生成,分两条路径:
- JSON 模式(
-j):以{"place": {...}}信封输出完整Place对象,字段为id、name、formatted_address、google_maps_uri; - 人类模式:按行输出
字段\t值,且只打印非空字段——id恒输出,name、address、maps_uri仅在有值时出现;若拿到空结果则向 stderr 打印No place并正常退出。
一个典型用法是把它接入脚本取地图链接:
gog maps places search "Brandenburg Gate Berlin" -j \ | jq -r '.place.google_maps_uri'或取坐标线索做后续处理:
gog maps places search "Eiffel Tower" -p # id ChIJd8... # name Eiffel Tower # address Avenue Gustave Eiffel, 75007 Paris, France # maps_uri https://maps.google.com/?cid=...注意--select是“尽力而为”的字段筛选(帮助文本明确建议多数命令优先用--fields思路),而--results-only用于裁掉信封字段——对本命令这种单结果输出,两者通常不是必需的。
源码级剖析:从 Run 到 HTTP 请求
调用链
MapsPlacesSearchCmd.Run(internal/cmd/maps.go)的流程为:
- 拼接并 Trim 查询串,为空则返回
missing query; - 调 newMapsPlacesClient:先经
placesAPIKey取密钥,再用googleapi.NewPlacesClient构建客户端,并用环境变量GOG_PLACES_BASE_URL覆盖默认 base URL(测试与本地调试钩子); - 调用
client.TextSearch(ctx, query, opts),随后交给writeMapsPlace输出。
TextSearch 的接口形态
核心 HTTP 逻辑在 internal/googleapi/places.go:
- 端点:
POST {baseURL}/places:searchText,默认 base URL 为https://places.googleapis.com/v1(Places API v1); - 请求体:
{"textQuery": <query>},非空时追加languageCode、regionCode; - 鉴权与字段掩码:密钥放在
X-Goog-Api-Key请求头,X-Goog-FieldMask固定为places.id,places.displayName,places.formattedAddress,places.googleMapsUri——即客户端只索取这四个字段,响应体被限制在 2 MB 内读取(io.LimitReader),HTTP 超时 10 秒(见 NewPlacesClient); - 结果策略:命令只返回
places数组中的第一个匹配项,映射为Place{ID, Name, FormattedAddress, GoogleMapsURI};数组为空时报no places matched: <query>。
也就是说,gog maps places search的语义是“取最佳匹配的单条结果”。如果你需要完整结果列表,可以走 gogcli 的通用 raw API 通道(参见 raw-api.md),或基于id接着调gog maps places details <placeId>取详情。
错误边界
doJSON 与非 2xx 状态处理(placesAPIError)会解析 Google 标准error.message/error.status,包装为places API error <code> <status>: <message>形式抛出——密钥无效、配额超限等场景在终端里会直接看到 Google 的原始错误信息,便于排障。
测试证据:如何验证这个命令的行为
单元测试 internal/cmd/maps_test.go 中的TestMapsPlacesSearch给出了一个可直接参考的端到端验证方式:
- 起一个
httptest本地服务器,断言请求为POST /places:searchText且携带X-Goog-Api-Key: test-key; - 通过
GOG_PLACES_API_KEY=test-key与GOG_PLACES_BASE_URL=<测试服务器地址>两个环境变量把真实客户端指向 mock; - 以
[]string{"cafe"}构造查询运行命令,断言 JSON 输出包含 place id、名称与 maps URI。
这个模式也说明了GOG_PLACES_BASE_URL的设计意图:无需真实密钥即可离线复现、调试整个 Places 搜索链路。同文件的TestMapsDirections、TestMapsGeocode对 directions/geocode 分支采用同样手法。
小结与关联命令
gog maps places search是 Places API v1 文本搜索的极简封装:多段 query 拼接、单条最佳结果、四字段精简输出、密钥三级配置(GOG_PLACES_API_KEY→GOOGLE_PLACES_API_KEY→config set places_api_key);- 拿到
id后可用gog maps places details <id>(docs/commands/gog-maps-places-details.md)深入取详情,二者共用同一PlacesClient与PlacesLookupOptions; - 路线、距离矩阵、地理编码由同文件内的
MapsDirectionsCmd/MapsDistanceCmd/MapsGeocodeCmd/MapsReverseGeocodeCmd提供,同样受GOG_MAPS_BASE_URL覆盖钩子与同一密钥配置约束(见 internal/cmd/maps.go); - 该命令为只读查询,
--dry-run、--readonly等安全 flag 语义与其它命令一致,可直接纳入 CI 或 Agent 工作流(配合--no-input、-j、-p获得稳定、可解析的输出)。
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考