Menu
CoddyTech

エクスポートと非エクスポート

CoddyのGOジャーニー「論理とフロー」セクションの一部。レッスン 52/68。

Go では、識別子(変数、関数、型など)の可視性は、単純な命名規則によって制御されます。これによって、他のパッケージのコードがあなたの識別子にアクセスできるかどうかが決まります。

エクスポートされた識別子は大文字で始まり、他のパッケージからアクセスできます。「public(公開)」と考えてください。あなたのパッケージをインポートする人なら誰でも使用できます。

// これらはエクスポートされます(公開されます)
var Name string
func Calculate() int
type Person struct

非公開識別子は小文字で始まり、同じパッケージ内でのみアクセスできます。これらはパッケージ内で「非公開」です。

// これらはエクスポートされていません(非公開です)
var age int
func helper() string
type config struct

この命名規則は、public や private のようなキーワードを使わずにアクセスを制御する Go の方法です。別のパッケージからエクスポートされていない識別子を使おうとすると、その識別子はパッケージの外から見えないため、Go はコンパイルエラーを出します。

challenge icon

チャレンジ

簡単

エクスポートされた識別子とエクスポートされていない識別子の命名規則を正しくすることで、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")です。

課題:

  1. 最初の入力をパイプで分割し、個々のパッケージ定義を取得する
  2. 各パッケージ定義をコロンで分割し、パッケージ名と識別子を取得する
  3. 各識別子の定義をコロンで分割し、識別子名、型、意図された可視性を取得する
  4. 識別子名と意図された可視性を受け取り、修正後の名前を返す fixIdentifierName という関数を作成する:
    • 可視性が "public" の場合、識別子の先頭が大文字になるようにする
    • 可視性が "private" の場合、識別子の先頭が小文字になるようにする
  5. パッケージ分析のヘッダーを表示する: "=== PACKAGE VISIBILITY ANALYSIS ==="
  6. 各パッケージについて、パッケージ情報を表示する:
    • "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 unknown.[identifier_name]: ✗ NOT FOUND"(パッケージ名として unknown を出力する。この試行は拒否されたアクセスとして数える)
    • 集計情報を数えて表示する:
      • "=== 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 の命名規則がパッケージの可視性を制御する仕組みを示し、エクスポートされた識別子とエクスポートされていない識別子の違いを理解できます。

自分で試してみよう

package main

import (
	"fmt"
	"strings"
)

func main() {
	// 入力を読み取る
	var packageDefinitions string
	var accessAttempts string
	fmt.Scanln(&packageDefinitions)
	fmt.Scanln(&accessAttempts)

	// TODO: 以下にコードを書く
	
	// fixIdentifierName関数を作成する
	
	// パッケージ定義を解析する
	
	// パッケージの分析結果を表示する
	
	// アクセス試行を解析する
	
	// アクセスの検証結果を表示する
	
	// 集計統計を計算して表示する
	
	// 推奨事項を表示する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

論理とフローのすべてのレッスン

自分で練習してみよう: Goオンラインコンパイラ