Menu
CoddyTech

Được xuất và không được xuất

Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 52 trên 68.

Trong Go, quy tắc đặt tên đơn giản quyết định khả năng hiển thị của các định danh (biến, hàm, kiểu dữ liệu, v.v.). Quy tắc này xác định liệu code từ các package khác có thể truy cập các định danh của bạn hay không.

Các định danh được xuất bắt đầu bằng chữ cái viết hoa và có thể được truy cập từ các package khác. Hãy xem chúng như những định danh “công khai”: bất kỳ ai nhập package của bạn đều có thể sử dụng chúng.

// Các tên này được xuất ra (công khai)
var Name string
func Calculate() int
type Person struct

Định danh không được xuất bắt đầu bằng chữ cái thường và chỉ có thể được truy cập trong cùng một package. Chúng là thành phần “riêng tư” trong package của bạn.

// Những mục này không được export (chỉ dùng nội bộ)
var age int
func helper() string
type config struct

Quy ước đặt tên này giúp Go kiểm soát quyền truy cập mà không cần các từ khóa như public hoặc private. Khi bạn cố dùng một định danh chưa được xuất từ package khác, Go sẽ báo lỗi biên dịch vì định danh đó không hiển thị bên ngoài package của nó.

challenge icon

Thử thách

Dễ

Sửa các vấn đề về khả năng hiển thị trong một package Go bằng cách chỉnh quy tắc đặt tên cho các định danh được xuất và không được xuất. Bạn sẽ làm việc với một tình huống mô phỏng có nhiều package, trong đó một số định danh được đặt tên không đúng, gây ra lỗi biên dịch khi các package khác truy cập chúng.

Bạn sẽ nhận hai đầu vào:

  • Một chuỗi chứa các định nghĩa package theo định dạng "package_name:identifier1:type1:visibility1,identifier2:type2:visibility2|package_name:identifier1:type1:visibility1" (ví dụ: "utils:helper:function:private,Calculate:function:public|main:name:variable:private,Version:variable:public")
  • Một chuỗi chứa các lần thử truy cập theo định dạng "accessing_package.identifier1,accessing_package.identifier2,accessing_package.identifier3" (ví dụ: "main.helper,main.Calculate,utils.Version")

Nhiệm vụ của bạn là:

  1. Phân tích đầu vào thứ nhất bằng cách tách theo dấu gạch đứng để lấy từng định nghĩa package
  2. Với mỗi định nghĩa package, tách theo dấu hai chấm để lấy tên package và các định danh của package đó
  3. Với mỗi định nghĩa định danh, tách theo dấu hai chấm để lấy tên, kiểu và khả năng hiển thị dự kiến của định danh
  4. Tạo một hàm có tên fixIdentifierName, nhận tên định danh và khả năng hiển thị dự kiến, rồi trả về tên đã chỉnh sửa:
    • Nếu khả năng hiển thị là "public", hãy đảm bảo định danh bắt đầu bằng chữ cái viết hoa
    • Nếu khả năng hiển thị là "private", hãy đảm bảo định danh bắt đầu bằng chữ cái viết thường
  5. Hiển thị tiêu đề phân tích package: "=== PACKAGE VISIBILITY ANALYSIS ==="
  6. Với mỗi package, hiển thị thông tin package:
    • "Package: [package_name]"
    • Với mỗi định danh trong package:
      • Nếu cần chỉnh sửa tên định danh: "- [original_name] ([type]) -> [corrected_name] (visibility: [visibility])"
      • Nếu tên định danh đã đúng: "- [identifier_name] ([type]) (visibility: [visibility]) ✓"
    • Phân tích đầu vào thứ hai bằng cách tách theo dấu phẩy để lấy từng lần thử truy cập
    • Với mỗi lần thử truy cập, tách theo dấu chấm để lấy package truy cập và định danh được truy cập
    • Hiển thị tiêu đề kiểm tra quyền truy cập: "=== ACCESS VALIDATION ==="
    • Với mỗi lần thử truy cập, xác định xem có thể truy cập hay không:
      • Tìm package chứa định danh đó
      • Kiểm tra xem tên định danh đã chỉnh sửa có bắt đầu bằng chữ cái viết hoa hay không (được xuất)
      • Nếu định danh được xuất: "[accessing_package] accessing [target_package].[corrected_identifier_name]: ✓ ALLOWED (exported)"
      • Nếu định danh không được xuất: "[accessing_package] accessing [target_package].[corrected_identifier_name]: ✗ DENIED (unexported)"
      • Nếu định danh không tồn tại: "[accessing_package] accessing unknown.[identifier_name]: ✗ NOT FOUND" (in từ unknown làm tên package; lần thử này được tính là một lần truy cập bị từ chối)
    • Đếm và hiển thị số liệu thống kê tổng kết:
      • "=== 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]"
    • Hiển thị đề xuất cuối cùng:
      • Nếu có định danh cần chỉnh sửa: "Recommendation: Fix identifier naming to follow Go conventions"
      • Nếu tất cả định danh đều đúng: "All identifiers follow proper Go naming conventions"

Dùng package strings để tách các chuỗi đầu vào, package fmt để in kết quả theo định dạng và các hàm xử lý chuỗi để kiểm tra, chỉnh sửa tên định danh. Thử thách này minh họa cách quy tắc đặt tên của Go kiểm soát khả năng hiển thị trong package, đồng thời giúp bạn hiểu sự khác nhau giữa định danh được xuất và không được xuất.

Tự làm thử

package main

import (
	"fmt"
	"strings"
)

func main() {
	// Đọc đầu vào
	var packageDefinitions string
	var accessAttempts string
	fmt.Scanln(&packageDefinitions)
	fmt.Scanln(&accessAttempts)

	// TODO: Viết code của bạn bên dưới
	
	// Tạo hàm fixIdentifierName
	
	// Phân tích các định nghĩa package
	
	// Hiển thị kết quả phân tích package
	
	// Phân tích các lần thử truy cập
	
	// Hiển thị kết quả xác thực truy cập
	
	// Tính và hiển thị số liệu thống kê tổng hợp
	
	// Hiển thị các đề xuất
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch Go online