エクスポートと非エクスポート
CoddyのGOジャーニー「論理とフロー」セクションの一部 — レッスン 52/68。
Goでは、識別子(変数、関数、型など)の可視性は、シンプルな命名規則によって制御されます。これにより、他のパッケージのコードがあなたの識別子にアクセスできるかどうかが決まります。
エクスポートされた識別子は、大文字で始まり、他のパッケージからアクセス可能です。それらは「パブリック」なものと考えてください。あなたのパッケージをインポートする誰もが使用できます。
// これらは公開(エクスポート)されています
var Name string
func Calculate() int
type Person structエクスポートされていない識別子は小文字で始まり、同じパッケージ内からのみアクセス可能です。これらはパッケージに対して「プライベート」なものです。
// これらはエクスポートされていません(非公開)
var age int
func helper() string
type config structこの命名規則は、publicやprivateといったキーワードを必要とせずにアクセスを制御するための、Go独自の方法です。別のパッケージからエクスポートされていない識別子を使用しようとすると、その識別子はパッケージの外からは見えないため、Goはコンパイルエラーを返します。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
チャレンジ
簡単エクスポートされた識別子とエクスポートされていない識別子の命名規則を修正することで、Goパッケージの可視性の問題を解決します。一部の識別子が誤って命名されており、他のパッケージからアクセスしたときにコンパイルエラーが発生する、シミュレートされたマルチパッケージのシナリオに取り組みます。
2つの入力を受け取ります:
"package_name:identifier1:type1:visibility1,identifier2:type2:visibility2|package_name:identifier1:type1:visibility1"形式のパッケージ定義を含む文字列(例:"utils:helper:function:private,Calculate:function:public|main:name:variable:private,Version:variable:public")"accessing_package.identifier1,accessing_package.identifier2,accessing_package.identifier3"形式のアクセス試行を含む文字列(例:"main.helper,main.Calculate,utils.Version")
あなたのタスクは以下の通りです:
- 最初の入力をパイプ記号で分割して、個々のパッケージ定義を取得します。
- 各パッケージ定義について、コロンで分割してパッケージ名とその識別子を取得します。
- 各識別子の定義について、コロンで分割して識別子名、型、および意図された可視性を取得します。
- 識別子名と意図された可視性を受け取り、修正された名前を返す
fixIdentifierNameという関数を作成します:- 可視性が
"public"の場合、識別子が大文字で始まるようにします。 - 可視性が
"private"の場合、識別子が小文字で始まるようにします。
- 可視性が
- パッケージ分析のヘッダーを表示します:
"=== PACKAGE VISIBILITY ANALYSIS ===" - 各パッケージについて、パッケージ情報を表示します:
"Package: [package_name]"- パッケージ内の各識別子について:
- 識別子名の修正が必要な場合:
"- [original_name] ([type]) -> [corrected_name] (visibility: [visibility])" - 識別子名が正しい場合:
"- [identifier_name] ([type]) (visibility: [visibility]) ✓"
- 識別子名の修正が必要な場合:
- 2番目の入力をカンマで分割して、個々のアクセス試行を取得します。
- 各アクセス試行について、ドットで分割してアクセス元のパッケージとアクセス対象の識別子を取得します。
- アクセス検証のヘッダーを表示します:
"=== ACCESS VALIDATION ===" - 各アクセス試行について、アクセスが有効かどうかを判断します:
- その識別子を含むパッケージを見つけます。
- 修正された識別子名が大文字で始まっているか(エクスポートされているか)を確認します。
- 識別子がエクスポートされている場合:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✓ ALLOWED (exported)" - 識別子がエクスポートされていない場合:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✗ DENIED (unexported)" - 識別子が存在しない場合:
"[accessing_package] accessing [target_package].[identifier_name]: ✗ NOT FOUND"
- 要約統計をカウントして表示します:
"=== SUMMARY ===""Total packages analyzed: [number_of_packages]""Total identifiers processed: [total_number_of_identifiers]""Identifiers requiring fixes: [number_of_identifiers_that_needed_fixing]""Access attempts: [number_of_access_attempts]""Allowed accesses: [number_of_allowed_accesses]""Denied accesses: [number_of_denied_accesses]"
- 最終的な推奨事項を表示します:
- 修正が必要な識別子があった場合:
"Recommendation: Fix identifier naming to follow Go conventions" - すべての識別子が正しかった場合:
"All identifiers follow proper Go naming conventions"
- 修正が必要な識別子があった場合:
入力文字列の分割には strings パッケージを、フォーマットされた出力には fmt パッケージを、識別子名の確認と変更には文字列操作関数を使用してください。このチャレンジは、Goの命名規則がパッケージの可視性をどのように制御するかを示し、エクスポートされた識別子とエクスポートされていない識別子の違いを理解するのに役立ちます。
チートシート
Goは、publicやprivateのような明示的なキーワードを使わず、命名規則を通じて可視性を制御します。
エクスポートされた識別子は、大文字で始まり、他のパッケージからアクセス可能です:
// これらはエクスポートされています(パブリック)
var Name string
func Calculate() int
type Person structエクスポートされていない識別子は、小文字で始まり、同じパッケージ内からのみアクセス可能です:
// これらはエクスポートされていません(プライベート)
var age int
func helper() string
type config struct他のパッケージからエクスポートされていない識別子にアクセスしようとすると、コンパイルエラーが発生します。
自分で試してみよう
package main
import (
"fmt"
"strings"
)
func main() {
// 入力を読み込む
var packageDefinitions string
var accessAttempts string
fmt.Scanln(&packageDefinitions)
fmt.Scanln(&accessAttempts)
// TODO: 以下にコードを記述してください
// fixIdentifierName 関数を作成する
// パッケージ定義を解析する
// パッケージ分析を表示する
// アクセス試行を解析する
// アクセス検証を表示する
// 要約統計を計算して表示する
// 推奨事項を表示する
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。